zoukankan      html  css  js  c++  java
  • [bzoj4771]七彩树

    首先考虑没有深度限制,即对一颗子树求颜色数,那么可以用树上差分,根据dfs序,每个点和这个颜色在dfs中上一次出现点的lca-1,然后每个点再打上一个+1,然后求一颗子树内所有节点的标记和即为答案。

    为了深度限制,因此可以以深度为时间建一棵可持久化线段树,然后查询(x,d)即查询第deep[x]+d层的以x为根的子树,同时过程中可以维护当前插入的节点中每一个颜色的set(根据dfs排序)来处理lca的加减。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100001
      4 #define mid (l+r>>1)
      5 struct ji{
      6     int nex,to;
      7 }edge[N<<1];
      8 int E,V,t,n,m,x,y,k,sz[N],c[N],r[N],sh[N],head[N],out[N],in[N],df[N],ndf[N],f[N][21],ls[N*100],rs[N*100],tr[N*100];
      9 set<int>se[N];
     10 struct node{
     11     int d,id; 
     12 }a[N];
     13 bool cmp(node  x,node y){
     14     return x.d<y.d; 
     15 }
     16 void add(int x,int y){
     17     edge[E].nex=head[x];
     18     edge[E].to=y;
     19     head[x]=E++;
     20 }
     21 void dfs(int k,int s){
     22     sz[k]=1;
     23     sh[k]=s;
     24     ndf[df[k]=++df[0]]=k;
     25     in[k]=++x;
     26     for(int i=head[k];i!=-1;i=edge[i].nex){
     27         dfs(edge[i].to,s+1);
     28         sz[k]+=sz[edge[i].to];
     29     }
     30     out[k]=++x;
     31 }
     32 bool pd(int x,int y){
     33     return (in[x]<=in[y])&&(out[y]<=out[x]);
     34 }
     35 int lca(int x,int y){
     36     if (pd(x,y))return x;
     37     if (pd(y,x))return y;
     38     for(int j=20;j>=0;j--)
     39         if (!pd(f[x][j],y))x=f[x][j];
     40     return f[x][0];
     41 }
     42 void update(int k1,int &k2,int l,int r,int x,int y){
     43     if ((x<l)||(x>r)||(l>r))return;
     44     tr[k2=++V];  
     45     ls[k2]=rs[k2]=0; 
     46     if (l==r){
     47         tr[k2]=tr[k1]+y;
     48         return;
     49     }
     50     update(ls[k1],ls[k2]=ls[k1],l,mid,x,y);
     51     update(rs[k1],rs[k2]=rs[k1],mid+1,r,x,y);
     52     tr[k2]=tr[ls[k2]]+tr[rs[k2]];
     53 }
     54 int query(int k,int l,int r,int x,int y){
     55     if ((x>r)||(l>y)||(l>r))return 0;
     56     if ((x<=l)&&(r<=y))return tr[k];
     57     return query(ls[k],l,mid,x,y)+query(rs[k],mid+1,r,x,y);
     58 }
     59 int main(){
     60     scanf("%d",&t);
     61     while (t--){
     62         scanf("%d%d",&n,&m);
     63         for(int i=1;i<=n;i++)scanf("%d",&c[i]);
     64         memset(head,-1,sizeof(head));
     65         E=V=df[0]=0;
     66         memset(r,0,sizeof(r));  
     67         for(int i=2;i<=n;i++){
     68             scanf("%d",&x);
     69             add(f[i][0]=x,i);
     70         }
     71         dfs(1,1); 
     72         f[1][0]=1; 
     73         for(int j=1;j<=20;j++)
     74             for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
     75         for(int i=1;i<=n;i++) a[i].id=i,a[i].d=sh[i];  
     76         sort(a+1,a+n+1,cmp);
     77         for(int i=1;i<=n;i++)se[i].clear();
     78         for(int i=1;i<=n;i++){
     79             k=a[i].id;  
     80             update(r[sh[a[i-1].id]],r[sh[k]],1,n,df[k],1);
     81             x=y=0;
     82             set<int>::iterator it=se[c[k]].lower_bound(df[k]);
     83             if (it!=se[c[k]].end())x=ndf[*it];
     84             if (it!=se[c[k]].begin())y=ndf[*(--it)];
     85             if (x)update(r[sh[k]],r[sh[k]],1,n,df[lca(x,k)],-1);
     86             if (y)update(r[sh[k]],r[sh[k]],1,n,df[lca(y,k)],-1);
     87             if ((x)&&(y))update(r[sh[k]],r[sh[k]],1,n,df[lca(x,y)],1);
     88             se[c[k]].insert(df[k]);
     89         }
     90         k=0;
     91         for(int i=1;i<=n;i++) if(!r[i]) r[i]=r[i-1];  
     92         while (m--){
     93             scanf("%d%d",&x,&y);
     94             x^=k;
     95             y^=k;  
     96             y=min(y+sh[x],n);  
     97             printf("%d\n",k=query(r[y],1,n,df[x],df[x]+sz[x]-1));
     98         }
     99     }
    100 }
    View Code
  • 相关阅读:
    如何在CentOS系统中安装字体 51CTO.COM
    C++检查输入数据类型? 知乎
    义乌市爱因宝母婴用品有限公司_公司简介
    硬盘对拷必备 AGE USB/eSATA对拷机现卖场!_青岛行情中关村在线
    Download: Microsoft SQL Server Management Studio Express Microsoft Download Center Download Details
    今晚看啥
    nano接收器
    12306订票助手 (版本 3.5.0)
    Microsoft® SQL Server® 2008 Management Studio Express
    有线键盘和鼠标确实应该退出历史舞台了
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249947.html
Copyright © 2011-2022 走看看