• BZOJ 4999: This Problem Is Too Simple! DFS序 + LCA + 树状数组 + 离线


    Description

    给您一颗树,每个节点有个初始值。
    现在支持以下两种操作:
    1. C i x(0<=x<2^31) 表示将i节点的值改为x。
    2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点。

    Input

    第一行有两个整数N,Q(1 ≤N≤ 100,000;1 ≤Q≤ 200,000),分别表示节点个数和操作个数。
    下面一行N个整数,表示初始时每个节点的初始值。
    接下来N-1行,每行两个整数x,y,表示x节点与y节点之间有边直接相连(描述一颗树)。
    接下来Q行,每行表示一个操作,操作的描述已经在题目描述中给出。
     

    Output

    对于每个Q输出单独一行表示所求的答案。
     
    题解:这个做法,有点牵强吧.

    感觉像是空间不够闲着蛋疼才会这么去做.

    离线也不是很高级.

    对每种颜色建立一个基于 DFS 序的树状数组,权值代表的是一个点出现该颜色的次数.

    我们想要查询两点间出现该颜色的次数,只需提取出 DFS 序中对应两点间路径即可.

    可是由于空间不够用,只能按照所有颜色分类,依次离线处理一遍.

    写起来挺麻烦的......
    #include<bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) 
    #define maxn 300000 
    using namespace std;
    struct OPT
    {
        int type; 
        int a,b,c,tag;
        OPT(int type=0,int a=0,int b=0,int c=0,int tag=0):type(type),a(a),b(b),c(c),tag(tag){} 
    }opt[maxn]; 
    vector<OPT>G[maxn]; 
    struct BIT
    {
        #define N 300000 
        int C[maxn]; 
        int lowbit(int t)
        {
            return t & (-t); 
        }
        void update(int x,int delta)
        {
            while(x<N) 
            {
                C[x]+=delta; 
                x+=lowbit(x); 
            }
        }
        int query(int x)
        {
            int tmp=0;
            while(x>0)
            {
                tmp+=C[x]; 
                x-=lowbit(x); 
            }
            return tmp; 
        }
    }tree; 
    char str[10]; 
    int n,Q,edges,tot,tim,mkk=0;  
    int col[maxn],Arr[maxn],hd[maxn],to[maxn<<1],nex[maxn<<1],dfn[maxn],ln[maxn],st[maxn],ed[maxn]; 
    int siz[maxn],hson[maxn],dep[maxn],top[maxn],fa[maxn],answer[maxn]; 
    void add(int u,int v)
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
    } 
    void dfs1(int u,int ff)
    {
        ln[++tim]=u,dfn[u]=st[u]=tim,siz[u]=1,dep[u]=dep[ff]+1,fa[u]=ff;  
        for(int i=hd[u];i;i=nex[i])
        {
            int v=to[i];
            if(v==ff) continue; 
            dfs1(v,u); 
            siz[u]+=siz[v]; 
            if(siz[v]>siz[hson[u]]) hson[u]=v; 
        }
        ed[u]=tim; 
    } 
    void dfs2(int u,int tp)
    {
        top[u]=tp; 
        if(hson[u]) dfs2(hson[u],tp); 
        for(int i=hd[u];i;i=nex[i])
        {
            int v=to[i];
            if(v==fa[u]||v==hson[u]) continue; 
            dfs2(v,v); 
        } 
    }
    int LCA(int x,int y)
    {     
        while(top[x]^top[y]) dep[top[x]] > dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
        return dep[x]<dep[y]?x:y;  
    }
    void solve(int cur)
    {
        for(int i=0,sz=G[cur].size();i<sz;++i)
        {
            OPT cn=G[cur][i];
            switch(cn.type)
            {
                case -1: 
                {
                    int u=cn.a; 
                    tree.update(st[u], -1); 
                    tree.update(ed[u]+1, +1);
                    break;  
                }
                case 1 : 
                {
                    int u=cn.a; 
                    tree.update(st[u], 1); 
                    tree.update(ed[u]+1, -1); 
                    break; 
                }
                case 2 : 
                {
                    int u=cn.a;
                    int v=cn.b;
                    int c=cn.c;
                    int g=cn.tag; 
                    int lca = LCA(u,v);  
                    answer[g]=tree.query(dfn[u])+tree.query(dfn[v])-tree.query(dfn[lca])-tree.query(dfn[fa[lca]]); 
                    break; 
                }
            }
        }
        for(int i=0,sz=G[cur].size();i<sz;++i)
        {
            OPT cn=G[cur][i]; 
            if(cn.type==-1) tree.update(st[cn.a], +1), tree.update(ed[cn.a]+1,-1); 
            if(cn.type==1)  tree.update(st[cn.a], -1), tree.update(ed[cn.a]+1, +1); 
        }
    }
    int main()
    {
        // setIO("input");     
        scanf("%d%d",&n,&Q);
        for(int i=1;i<=n;++i) scanf("%d",&col[i]),Arr[++tot]=col[i];          
        for(int i=1;i<n;++i)
        {
            int x,y; 
            scanf("%d%d",&x,&y); 
            add(x,y), add(y,x); 
        }
        dfs1(1,0); 
        dfs2(1,1);  
        for(int i=1;i<=Q;++i)
        {
            scanf("%s",str); 
            switch(str[0])
            {
                case 'C' :
                {
                    opt[i].type=1; 
                    scanf("%d%d",&opt[i].a,&opt[i].b);
                    Arr[++tot]=opt[i].b; 
                    break;  
                }
                case 'Q' :
                {
                    opt[i].type=2; 
                    scanf("%d%d%d",&opt[i].a,&opt[i].b,&opt[i].c);
                    Arr[++tot]=opt[i].c;  
                    break; 
                }
            }
        }
        sort(Arr+1,Arr+1+tot);  
        for(int i=1;i<=Q;++i) 
        {
            if(opt[i].type==1) opt[i].b=lower_bound(Arr+1,Arr+1+tot,opt[i].b)-Arr;
            if(opt[i].type==2) opt[i].c=lower_bound(Arr+1,Arr+1+tot,opt[i].c)-Arr; 
        }  
        for(int i=1;i<=n;++i) 
        {
            col[i]=lower_bound(Arr+1,Arr+1+tot,col[i])-Arr;
            G[col[i]].push_back(OPT(1,i,0,0,0)); 
        }
        for(int i=1;i<=Q;++i)
        {
            if(opt[i].type==2)
            {
                OPT P=opt[i]; 
                P.tag=++mkk; 
                G[opt[i].c].push_back(P);
            } 
            else 
            { 
                int u=opt[i].a,v=opt[i].b;
                G[col[u]].push_back(OPT(-1,u,0,0,0)); 
                G[v].push_back(OPT(1,u,0,0,0));
                col[u]=v;  
            }
        }     
        for(int i=1;i<maxn;++i) 
        {
            if(G[i].size()) solve(i); 
        }
        for(int i=1;i<=mkk;++i) 
        {   
            printf("%d
    ",answer[i]); 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    CSS页面渲染优化属性will-change
    前端自动化构建工具-yoman浅谈
    【积累】如何优雅关闭SpringBoot Web服务进程
    SpringCloud Eureka Client和Server侧配置及Eureka高可用配置
    SpringBoot返回html页面
    MySQL8主从配置
    使用Arrays.asList抛出java.lang.UnsupportedOperationException
    SpringMVC+Mybatis+MySQL8遇到的问题
    MySQL5.6启用sha256_password插件
    Base64简单原理
  • 原文地址:https://www.cnblogs.com/guangheli/p/11016340.html
Copyright © 2020-2023  润新知