zoukankan      html  css  js  c++  java
  • [BZOJ]2017省队十连测推广赛1 T2.七彩树

    题目大意:给你一棵n个点的树,每个点有颜色,m次询问,每次询问一个点x的子树内深度不超过depth[x]+d的节点的颜色数量,强制在线。(n,m<=100000,多组数据,保证n,m总和不超过500000)

    思路:若不考虑深度限制,我们可以先给每个点赋点权1,再把每种颜色的节点按dfs序排序后相邻的节点的LCA的点权减1,每次求子树和即可回答询问,若有限制深度,我们可以按深度顺序把点一个个加入树中,每种颜色用个set维护,强制在线只要把求子树和的线段树可持久化就可以了,总复杂度O(nlogn)。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 100000
    #define K 17
    #define ND 8000000
    struct edge{int nx,t;}e[MN+5];
    int h[MN+5],en,c[MN+5],d[MN+5],l[MN+5],r[MN+5],cnt,fa[K][MN+5],p[MN+5],rt[MN+5],tn;
    class stcmp{public:inline bool operator()(int a,int b){return l[a]<l[b];}};
    set<int,stcmp> st[MN+5];
    set<int,stcmp>::iterator x,y,z;
    struct node{int l,r,s;}t[ND+5];
    int renew(int x,int l,int r,int k,int z)
    {
        int p=++tn,mid=l+r>>1;
        if(l==r)return t[p]=(node){0,0,t[x].s+z},p;
        if(k<=mid)return t[p]=(node){renew(t[x].l,l,mid,k,z),t[x].r,t[x].s+z},p;
        return t[p]=(node){t[x].l,renew(t[x].r,mid+1,r,k,z),t[x].s+z},p;
    }
    int query(int x,int l,int r,int L,int R)
    {
        if(l==L&&r==R)return t[x].s;
        int mid=l+r>>1;
        if(R<=mid)return query(t[x].l,l,mid,L,R);
        if(L>mid)return query(t[x].r,mid+1,r,L,R);
        return query(t[x].l,l,mid,L,mid)+query(t[x].r,mid+1,r,mid+1,R);
    }
    inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;}
    void dfs(int x)
    {
        l[x]=++cnt;
        for(int i=h[x];i;i=e[i].nx)d[e[i].t]=d[x]+1,dfs(e[i].t);
        r[x]=cnt;
    }
    bool cmp(int a,int b){return d[a]<d[b];}
    int lca(int x,int y)
    {
        int dx=d[x]-d[y],i;
        if(dx<0)dx=-dx,swap(x,y);
        for(i=0;dx;dx>>=1,++i)if(dx&1)x=fa[i][x];
        if(x==y)return x;
        for(i=K;i--;)if(fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y];
        return fa[0][x];
    }
    int main()
    {
        int T,n,m,i,j,t;
        for(T=read();T--;)
        {
            n=read();m=read();
            for(i=1;i<=n;++i)c[i]=read(),p[i]=i,st[i].clear();
            memset(h,t=tn=en=cnt=0,sizeof(int)*(n+1));
            for(i=2;i<=n;++i)ins(fa[0][i]=read(),i);
            for(i=1;i<K;++i)for(j=1;j<=n;++j)fa[i][j]=fa[i-1][fa[i-1][j]];
            dfs(1);sort(p+1,p+n+1,cmp);
            for(i=1;i<=n;++i)
            {
                t=renew(t,1,n,l[p[i]],1);
                st[c[p[i]]].insert(p[i]);
                x=y=z=st[c[p[i]]].find(p[i]);--x;++z;
                if(y!=st[c[p[i]]].begin()&&z!=st[c[p[i]]].end())t=renew(t,1,n,l[lca(*x,*z)],1);
                if(y!=st[c[p[i]]].begin())t=renew(t,1,n,l[lca(*x,*y)],-1);
                if(z!=st[c[p[i]]].end())t=renew(t,1,n,l[lca(*y,*z)],-1);
                rt[d[p[i]]]=t;
            }
            for(t=0;m--;)
            {
                i=read()^t;j=read()^t;
                printf("%d
    ",t=query(rt[d[i]+j>d[p[n]]?d[p[n]]:d[i]+j],1,n,l[i],r[i]));
            }
        }
    }
  • 相关阅读:
    HTTP概述
    【HTTP权威指南】第二章URL与资源
    【HTTP权威指南】第三章HTTP报文
    列表生成式
    六一问候
    NYOJ 528 找球号(三)
    NYOJ 138 找球号(二)
    HDU3790 最短路径问题
    NYOJ 228 士兵杀敌(五)
    NYOJ3 3 多边形重心问题
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ-2017-C2.html
Copyright © 2011-2022 走看看