• bzoj4771 七彩树


    传送门

    不得不说这是道好题……

    先考虑没有深度限制的情况,显然把每种颜色的点做一个树链的并,再求一个子树标记和就行了,这个没什么难度。

    然后考虑有了深度限制的情况,我们可以按深度从小到大依次加入所有点,对每个深度分别维护一棵线段树存储每个点的标记和,查询(x,d)的时候就在x的深度+d对应的线段树中查询子树标记和即可。不难发现每个深度的线段树都是可以从上一个快速更新得到的,那么就可以可持久化了,每次把当前深度的点加入并更新一下树链的并,因此还需要用set维护前驱后继。

    被set坑了好久,感觉一年半的STL都白学了……

      1 /**************************************************************
      2     Problem: 4771
      3     User: hzoier
      4     Language: C++
      5     Result: Accepted
      6     Time:2176 ms
      7     Memory:118204 kb
      8 ****************************************************************/
      9 #include<cstdio>
     10 #include<cstring>
     11 #include<algorithm>
     12 #include<vector>
     13 #include<set>
     14 using namespace std;
     15 const int maxn=100010,maxm=maxn<<6;
     16 void clear(int);
     17 void bfs();
     18 int LCA(int,int);
     19 void build(int,int,int&);
     20 void query(int,int,int);
     21 int copy(int);
     22 int sm[maxm]={0},lc[maxm]={0},rc[maxm]={0},vis[maxm]={0},root[maxn],cnt=0,tim;
     23 vector<int>G[maxn];
     24 int f[maxn][20],d[maxn],dfn[maxn],size[maxn],q[maxn];
     25 struct cmp{bool operator()(int x,int y)const{return dfn[x]<dfn[y];}};
     26 set<int,cmp>st[maxn];
     27 int T,n,m,lgn,a[maxn],x,s,t,k,ans;
     28 int main(){
     29     scanf("%d",&T);
     30     while(T--){
     31         scanf("%d%d",&n,&m);
     32         clear(n);
     33         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
     34         for(int i=2;i<=n;i++){
     35             scanf("%d",&f[i][0]);
     36             G[f[i][0]].push_back(i);
     37         }
     38         bfs();
     39         for(int j=1;j<=lgn;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
     40         for(int i=1;i<=n;i++){
     41             x=q[i];
     42             if(!root[d[x]])root[d[x]]=root[d[x]-1];
     43             tim=d[x];
     44             k=1;
     45             t=dfn[x];
     46             build(1,n,root[d[x]]);
     47             set<int,cmp>::iterator u=st[a[x]].lower_bound(x),v=st[a[x]].upper_bound(x);
     48             if(u==st[a[x]].begin())u=st[a[x]].end();
     49             else if(u!=st[a[x]].end())u--;
     50             else if(!st[a[x]].empty()&&dfn[*st[a[x]].rbegin()]<dfn[x])u=st[a[x]].find(*st[a[x]].rbegin());
     51             if(u!=st[a[x]].end()&&v!=st[a[x]].end()){
     52                 t=dfn[LCA(*u,*v)];
     53                 build(1,n,root[d[x]]);
     54             }
     55             k=-1;
     56             if(u!=st[a[x]].end()){
     57                 t=dfn[LCA(*u,x)];
     58                 build(1,n,root[d[x]]);
     59             }
     60             if(v!=st[a[x]].end()){
     61                 t=dfn[LCA(x,*v)];
     62                 build(1,n,root[d[x]]);
     63             }
     64             st[a[x]].insert(x);
     65         }
     66         for(int i=1;i<=n;i++)if(!root[i])root[i]=root[i-1];
     67         while(m--){
     68             scanf("%d%d",&x,&k);
     69             x^=ans;k^=ans;
     70             s=dfn[x];
     71             t=dfn[x]+size[x]-1;
     72             ans=0;
     73             query(1,n,root[min(d[x]+k,n)]);
     74             printf("%d
    ",ans);
     75         }
     76     }
     77     return 0;
     78 }
     79 void clear(int n){
     80     fill(sm,sm+cnt+1,0);
     81     fill(lc,lc+cnt+1,0);
     82     fill(rc,rc+cnt+1,0);
     83     fill(vis,vis+cnt+1,0);
     84     cnt=tim=0;
     85     fill(root,root+n+1,0);
     86     for(int i=0;i<=n;i++){
     87         G[i].clear();
     88         memset(f[i],0,sizeof(f[i]));
     89         st[i].clear();
     90     }
     91     fill(d,d+n+1,0);
     92     fill(dfn,dfn+n+1,0);
     93     fill(size,size+n+1,0);
     94     lgn=ans=0;
     95 }
     96 void bfs(){
     97     int x,head=1,tail=1;
     98     q[tail++]=1;
     99     while(head!=tail){
    100         x=q[head++];
    101         dfn[x]=size[x]=1;
    102         d[x]=d[f[x][0]]+1;
    103         while((1<<lgn)<d[x])lgn++;
    104         for(int i=0;i<(int)G[x].size();i++)q[tail++]=G[x][i];
    105     }
    106     for(int i=n;i>1;i--){
    107         x=q[i];
    108         dfn[x]+=size[f[x][0]];
    109         size[f[x][0]]+=size[x];
    110     }
    111     for(int i=2;i<=n;i++)dfn[q[i]]+=dfn[f[q[i]][0]]-1;
    112 }
    113 int LCA(int x,int y){
    114     if(d[x]!=d[y]){
    115         if(d[x]<d[y])swap(x,y);
    116         for(int i=lgn;i>=0;i--)if(d[f[x][i]]>=d[y])x=f[x][i];
    117     }
    118     if(x==y)return x;
    119     for(int i=lgn;i>=0;i--)if(f[x][i]!=f[y][i]){
    120         x=f[x][i];
    121         y=f[y][i];
    122     }
    123     return f[x][0];
    124 }
    125 void build(int l,int r,int &rt){
    126     if(vis[rt]<tim)rt=copy(rt);
    127     sm[rt]+=k;
    128     if(l==r)return;
    129     int mid=(l+r)>>1;
    130     if(t<=mid)build(l,mid,lc[rt]);
    131     else build(mid+1,r,rc[rt]);
    132 }
    133 void query(int l,int r,int rt){
    134     if(!rt)return;
    135     if(s<=l&&t>=r){
    136         ans+=sm[rt];
    137         return;
    138     }
    139     int mid=(l+r)>>1;
    140     if(s<=mid)query(l,mid,lc[rt]);
    141     if(t>mid)query(mid+1,r,rc[rt]);
    142 }
    143 int copy(int rt){
    144     int x=++cnt;
    145     sm[x]=sm[rt];
    146     lc[x]=lc[rt];
    147     rc[x]=rc[rt];
    148     vis[x]=tim;
    149     return x;
    150 }
    View Code
  • 相关阅读:
    c# CLR无法从 COM 上下文 0x51cd20 转换为 COM 上下文 0x51ce90
    sql语法
    学籍管理系统
    【Android进阶】Android调用WebService的实现
    【Android进阶】自定义控件实现底部扇形展开菜单效果
    华为上机题汇总----java
    卡片游戏(栈和队列)
    18岁生日
    循环多少次?
    Flappy bird源代码(略吊)
  • 原文地址:https://www.cnblogs.com/hzoier/p/6606262.html
Copyright © 2020-2023  润新知