zoukankan      html  css  js  c++  java
  • Bzoj4771 七彩树

    Time Limit: 5 Sec  Memory Limit: 256 MB
    Submit: 646  Solved: 189

    Description

    给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点。每个节点都被染上了某一种颜色,其中第i个节
    点的颜色为c[i]。如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色。定义depth[i]为i节点与根节点的距离
    ,为了方便起见,你可以认为树上相邻的两个点之间的距离为1。站在这棵色彩斑斓的树前面,你将面临m个问题。
    每个问题包含两个整数x和d,表示询问x子树里且depth不超过depth[x]+d的所有点中出现了多少种本质不同的颜色
    。请写一个程序,快速回答这些询问。

    Input

    第一行包含一个正整数T(1<=T<=500),表示测试数据的组数。
    每组数据中,第一行包含两个正整数n(1<=n<=100000)和m(1<=m<=100000),表示节点数和询问数。
    第二行包含n个正整数,其中第i个数为c[i](1<=c[i]<=n),分别表示每个节点的颜色。
    第三行包含n-1个正整数,其中第i个数为f[i+1](1<=f[i]<i),表示节点i+1的父亲节点的编号。
    接下来m行,每行两个整数x(1<=x<=n)和d(0<=d<n),依次表示每个询问。
    输入数据经过了加密,对于每个询问,如果你读入了x和d,那么真实的x和d分别是x xor last和d xor last,
    其中last表示这组数据中上一次询问的答案,如果这是当前数据的第一组询问,那么last=0。
    输入数据保证n和m的总和不超过500000。

    Output

    对于每个询问输出一行一个整数,即答案。

    Sample Input

    1
    5 8
    1 3 3 2 2
    1 1 3 3
    1 0
    0 0
    3 0
    1 3
    2 1
    2 0
    6 2
    4 1

    Sample Output

    1
    2
    3
    1
    1
    2
    1
    1

    HINT

     

    Source

    树 dfs序 主席树 脑洞题

    Claris神犇的题果然画风清奇

    说到子树查询大概就是dfs序了吧

    然而这个深度限制怎么搞啊……

    如果不考虑深度限制的话,可以在树上做差分,若两个点同色,它们的权值为1,并且它们的LCA的权值-1,这样求子树和就能得到正确信息。

    用主席树按深度递增顺序,以dfs序为下标添加值并维护差分,这样rt[dep[x]+k]-rt[dep[x]]的范围就是需要的信息了。

    真是神奇

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 #include<set>
      9 using namespace std;
     10 const int mxn=100010;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 inline int min(int a,int b){return a<b?a:b;}//
     18 struct edge{
     19     int v,nxt;
     20 }e[mxn<<1];
     21 int hd[mxn],mct=0;
     22 void add_edge(int u,int v){
     23     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     24 }
     25 //
     26 int fa[mxn][18];
     27 int dfn[mxn],out[mxn],dtime=0;
     28 int dep[mxn],id[mxn];
     29 int cmp(int a,int b){
     30     return dep[a]<dep[b];
     31 }
     32 void DFS(int u,int ff){
     33     dfn[u]=++dtime;
     34     dep[u]=dep[ff]+1;
     35     for(int i=1;i<=17;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
     36     for(int i=hd[u],v;i;i=e[i].nxt){
     37         v=e[i].v;
     38         if(v==ff)continue;
     39         fa[v][0]=u;
     40         DFS(v,u);
     41     }
     42     out[u]=dtime;
     43     return;
     44 }
     45 int LCA(int x,int y){
     46     if(dep[x]<dep[y])swap(x,y);
     47     for(int i=17;i>=0;i--)
     48         if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
     49     if(x==y)return y;
     50     for(int i=17;i>=0;i--)
     51         if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
     52     return fa[x][0];
     53 }
     54 /////LCA
     55 struct node{
     56     int l,r;
     57     int smm;
     58 }t[mxn*80];
     59 int rt[mxn<<2],cnt=0;//树根 
     60 int TP[mxn],dct=0;//树根head
     61 void update(int p,int v,int l,int r,int y,int &rt){
     62     rt=++cnt;
     63     t[rt]=t[y];
     64     t[rt].smm+=v;//标记永久化 
     65     if(l==r){return;}
     66     int mid=(l+r)>>1;
     67     if(p<=mid)update(p,v,l,mid,t[y].l,t[rt].l);
     68     else update(p,v,mid+1,r,t[y].r,t[rt].r);
     69     return;
     70 }
     71 int query(int L,int R,int l,int r,int rt){
     72     if(!rt)return 0;
     73     if(L<=l && r<=R){
     74         return t[rt].smm;
     75     }
     76     int mid=(l+r)>>1;
     77     int res=0;
     78     if(L<=mid)res+=query(L,R,l,mid,t[rt].l);
     79     if(R>mid)res+=query(L,R,mid+1,r,t[rt].r);
     80     return res;
     81 }
     82 /////SGT
     83 int n,m;
     84 struct pt{
     85     int dfn,v;
     86     friend bool operator < (pt a,pt b){return a.dfn<b.dfn;}
     87 };
     88 set<pt>st[mxn];
     89 void add(int dep,int x,int y,int v){
     90     int tmp=LCA(x,y);
     91 //    printf("dep:%d x:%d y:%d LCA:%d v:%d
    ",dep,x,y,tmp,v);
     92     update(dfn[tmp],v,1,n,rt[dct],rt[dct+1]);
     93     TP[dep]=++dct;
     94     return;
     95 }
     96 void insert(int c,int x){
     97     pt tmp=(pt){dfn[x],x};
     98     st[c].insert(tmp);
     99     add(dep[x],x,x,1);
    100     set<pt>::iterator it,itL,itR;
    101     it=st[c].lower_bound(tmp);
    102     itL=it;itL--;
    103     itR=it;itR++;
    104 /*    printf("nowc:%d nowx:%d
    ",c,x);
    105     if(it!=st[c].begin()){
    106         printf("left:%d
    ",(*itL).v);
    107     }
    108     if(itR!=st[c].end()){
    109         printf("right:%d
    ",(*itR).v);    
    110     }*/
    111     
    112     if(it!=st[c].begin() && itR!=st[c].end()){
    113         add(dep[x],(*itL).v,(*itR).v,1);
    114         add(dep[x],(*itL).v,x,-1);
    115         add(dep[x],x,(*itR).v,-1);
    116     }
    117     else if(it!=st[c].begin()){
    118         add(dep[x],(*itL).v,x,-1);
    119     }
    120     else if(itR!=st[c].end()){
    121         add(dep[x],x,(*itR).v,-1);
    122     }
    123     return;
    124 }
    125 /////SET
    126 int last=0,ans=0,mxdep=0;
    127 int c[mxn];
    128 void solve(){
    129     int x,d;
    130     for(int i=1;i<=m;i++){
    131         x=read()^last;d=read()^last;
    132         ans=query(dfn[x],out[x],1,n,rt[TP[min(mxdep,dep[x]+d)]]);
    133         last=ans;
    134         printf("%d
    ",ans);
    135     }
    136     return;
    137 }
    138 void init(int n){
    139     for(int i=1;i<=cnt;i++) t[i].l=t[i].r=t[i].smm=0;
    140 //    memset(t,0,sizeof t);
    141     memset(hd,0,sizeof hd);
    142     memset(rt,0,sizeof rt);
    143     memset(TP,0,sizeof TP);
    144     for(int i=1;i<=n;i++)
    145         st[i].clear();
    146     mct=0;cnt=0;
    147     last=ans=0;
    148     dct=0;dtime=0;
    149     return;
    150 }
    151 int main(){
    152     int i,j,u,v;
    153     int T=read();
    154     while(T--){
    155         n=read();m=read();
    156         init(n);
    157         for(i=1;i<=n;i++)
    158             c[i]=read();
    159         for(i=2;i<=n;i++){
    160             u=read();
    161             add_edge(u,i);
    162         }
    163         DFS(1,0);
    164         for(i=1;i<=n;i++)id[i]=i;
    165         sort(id+1,id+n+1,cmp);//按照深度排序
    166         for(i=1;i<=n;i++){
    167             u=id[i];int d=dep[u];
    168 //            printf("u:%d d:%d
    ",u,d);
    169             insert(c[u],u);
    170         }
    171         mxdep=dep[id[n]];
    172         solve();
    173     }
    174     return 0;
    175 }
  • 相关阅读:
    python判断语句和循环语句
    Web项目如何做单元测试
    PHP接口自动化测试框架实现
    引入缺陷的原因都有哪些?
    测试基础:(一)
    测试基础(二)
    测试术语2
    测试术语3
    测试术语4
    Spring Cloud Stream与Spring Cloud Bus区别?
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6663874.html
Copyright © 2011-2022 走看看