• UOJ#58. 【WC2013】糖果公园


    学了一波树上莫队

    想要自己YY出转移方法交代了一个晚修未遂。。

    现在的做法相当于是维护两条链,lca即用即删,好妙啊。。

    对于树分块,写的是[B,3B]的,看到有人写伪ETT括号序列的,不知道那个快呢。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int maxn=110000;
    const int maxm=110000;
    const int maxQ=110000;
    
    struct node
    {
        int x,y,next;
    }a[maxn*2];int len,last[maxn];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int block,z,st[maxn]; int top,sta[maxn];
    int Bin[30],f[30][maxn],dep[maxn];
    void dfs(int x)
    {
        for(int i=1;Bin[i]<=dep[x];i++)f[i][x]=f[i-1][f[i-1][x]];
        int now=top;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=f[0][x])
            {
                f[0][y]=x;
                dep[y]=dep[x]+1;
                dfs(y);
                if(top-now>=block)
                {
                    z++;
                    while(top!=now)st[sta[top--]]=z;
                }
            }
        }
        sta[++top]=x;
    }
    int LCA(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);
        for(int i=25;i>=0;i--)
            if(dep[x]-dep[y]>=Bin[i])x=f[i][x];
        if(x==y)return x;
        
        for(int i=25;i>=0;i--)
            if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
        return f[0][x];
    }
    
    //-----------------------------split----------------------------------------------------------------------
    
    struct Change{int x,nc,pc,t;}c[maxQ];int clen,clast[maxn];
    struct Query{int x,y,t;}q[maxQ];int qlen;LL as[maxQ];
    bool cmp(Query q1,Query q2)
    {
        return st[q1.x]==st[q2.x]? (st[q1.y]==st[q2.y]?q1.t<q2.t:st[q1.y]<st[q2.y]) : st[q1.x]<st[q2.x];
    }
    
    LL sum; 
    int co[maxn],s[maxn];//节点颜色,节点是否计入答案 
    LL num[maxm],v[maxm],w[maxn];//当前颜色出现次数,某颜色的价值,新奇指数 
    void change(int x,int col)
    {
        if(s[x]) sum-=w[num[co[x]]]*v[co[x]], num[co[x]]--;
        co[x]=col;
        if(s[x]) num[co[x]]++, sum+=w[num[co[x]]]*v[co[x]];
    }
    void res(int x)
    {
        if(!s[x]) num[co[x]]++, sum+=w[num[co[x]]]*v[co[x]];
        else      sum-=w[num[co[x]]]*v[co[x]], num[co[x]]--;
        s[x]^=1;
    }
    void zzz(int x,int y)
    {
        while(x!=y)
        {
            if(dep[x]>dep[y])res(x),x=f[0][x];
            else res(y),y=f[0][y];
        }
    }
    void solve(int Q)
    {
        int j=0; sum=0;
        q[0].x=q[0].y=1;
        for(int i=1;i<=qlen;i++)
        {
            while(j<clen&&c[j+1].t<q[i].t)j++,change(c[j].x,c[j].nc);
            while(j>0&&q[i].t<c[j].t)change(c[j].x,c[j].pc),j--;
            
            zzz(q[i-1].x,q[i].x);
            zzz(q[i-1].y,q[i].y);
            int lca=LCA(q[i].x,q[i].y);
            res(lca);
            as[q[i].t]=sum;
            res(lca);
        } 
    }
    
    //-----------------------------莫队----------------------------------------------------------------------
    
    int main()
    {
        int n,m,Q;
        scanf("%d%d%d",&n,&m,&Q);
        for(int i=1;i<=m;i++)scanf("%lld",&v[i]);
        for(int i=1;i<=n;i++)scanf("%lld",&w[i]);
        
        int x,y; len=1;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            ins(x,y),ins(y,x);
        }
        block=pow(x,2.0/3.0);
        Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2;
        z=0;dfs(1);
        z++;while(top!=0)st[sta[top--]]=z;
        for(int i=1;i<=n;i++)
            scanf("%d",&co[i]),clast[i]=co[i];
    
        int op=0;
        for(int i=1;i<=Q;i++)
        {
            scanf("%d",&op);
            if(op==0)
            {
                clen++;
                scanf("%d%d",&c[clen].x,&c[clen].nc),c[clen].t=i;
                c[clen].pc=clast[c[clen].x],clast[c[clen].x]=c[clen].nc;
            }
            else
            {
                qlen++;
                scanf("%d%d",&q[qlen].x,&q[qlen].y),q[qlen].t=i;
            }
        }
        sort(q+1,q+qlen+1,cmp);
        
        memset(as,-1,sizeof(as));
        solve(Q);
        for(int i=1;i<=Q;i++)
            if(as[i]!=-1)printf("%lld
    ",as[i]);
        
    
        return 0;
    }
  • 相关阅读:
    C语言实现数据结构中的顺序栈
    什么是A股什么是B股,为什么有AB股之分?
    C语言实现数据结构中的链队列
    C语言实现数据结构中的循环链表
    C语言实现数据结构的链表
    C语言中指针变量作为函数参数和一般变量作为函数参数的区别
    javascrip实现下拉框联动
    C语言实现数据结构中的顺序表
    C语言实现数据结构中的链栈
    SQL语句之基础增删改查 time
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10279586.html
Copyright © 2020-2023  润新知