• [HDU5709]Claris Loves Painting


    有一个$n$个点的树,每个点有一个颜色,每次询问$x$点子树内距离小于等于$d$的点的颜色个数,强制在线

    超级妙的一道题

    首先我们可以想想如果不强制在线我们可以怎么做

    $Dsu$ $on$ $tree$!

    首先把所有询问离线下来,然后用$vector$存下来每个点的询问

    按照深度建一个线段树表示深度小于等于$i$的点颜色个数有多少,开一个数组$d_i$表示颜色$i$出现的最低深度是多少

    很显然如果$d_i$都无法对答案产生贡献,那么子树内就不存在能对答案产生贡献的颜色$i$

    然后我们暴力遍历轻儿子的时候,如果当先前点为颜色$i$且当前点的深度小于$d_i$,就可以更新$d_i$的值

    然后从线段树中删除之前的$d_i$的贡献,假如新的$d_i$的贡献,最后查询线段树回答询问即可

    如果在线做我们也是要建一个类似的线段树保证查询的复杂度,问题是我们该如何求出子树中每种颜色最低的深度

    假如我们事先已经知道一个点$x$的所有子树内颜色的最低深度,那么我们就可以利用线段树合并把他们合起来

    然后对于回答询问的线段树的修改与之前是一样的,所以我们开两颗权值线段树就可以做出来这道题了

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define M 100010
     5 using namespace std;
     6 int n,m,T,cnt,ans;
     7 int fa[M],deep[M],c[M],rt1[M],rt2[M];
     8 int val[M<<7],ch[M<<7][2];
     9 int insert(int rt,int l,int r,int pos,int v)
    10 {
    11     int node=++cnt;val[node]=val[rt]+v;
    12     if(l==r) return node;
    13     int mid=(l+r)/2;
    14     ch[node][0]=ch[rt][0],ch[node][1]=ch[rt][1];
    15     if(pos<=mid) ch[node][0]=insert(ch[rt][0],l,mid,pos,v);
    16     else ch[node][1]=insert(ch[rt][1],mid+1,r,pos,v);
    17     return node;
    18 }
    19 int merge1(int x,int y,int l,int r)
    20 {
    21     if(!x||!y) return x+y;
    22     int node=++cnt;val[node]=val[x]+val[y];
    23     if(l==r) return node;
    24     int mid=(l+r)/2;
    25     ch[node][0]=merge1(ch[x][0],ch[y][0],l,mid);
    26     ch[node][1]=merge1(ch[x][1],ch[y][1],mid+1,r);
    27     return node;
    28 }
    29 int merge2(int x,int y,int l,int r,int id)
    30 {
    31     if(!x||!y) return x+y;
    32     int node=++cnt;
    33     if(l==r)
    34     {
    35         if(val[x]>val[y]) val[node]=val[y],rt1[id]=insert(rt1[id],1,n,val[x],-1);
    36         else val[node]=val[x],rt1[id]=insert(rt1[id],1,n,val[y],-1);
    37         return node;
    38     }
    39     int mid=(l+r)/2;
    40     ch[node][0]=merge2(ch[x][0],ch[y][0],l,mid,id);
    41     ch[node][1]=merge2(ch[x][1],ch[y][1],mid+1,r,id);
    42     return node;
    43 }
    44 int query(int node,int l,int r,int l1,int r1)
    45 {
    46     if(!node) return 0;
    47     if(l1==l&&r1==r) return val[node];
    48     int mid=(l+r)/2;
    49     if(r1<=mid) return query(ch[node][0],l,mid,l1,r1);
    50     else if(l1>mid) return query(ch[node][1],mid+1,r,l1,r1);
    51     else return query(ch[node][0],l,mid,l1,mid)+query(ch[node][1],mid+1,r,mid+1,r1);
    52 }
    53 void work()
    54 {
    55     cnt=ans=0;
    56     scanf("%d%d",&n,&m);
    57     for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    58     for(int i=2;i<=n;i++) scanf("%d",&fa[i]);
    59     for(int i=1;i<=n;i++) deep[i]=deep[fa[i]]+1;
    60     for(int i=1;i<=n;i++)
    61     {
    62         rt1[i]=insert(0,1,n,deep[i],1);
    63         rt2[i]=insert(0,1,n,c[i],deep[i]);
    64     }
    65     for(int i=n;i>=2;i--)
    66     {
    67         rt1[fa[i]]=merge1(rt1[fa[i]],rt1[i],1,n);
    68         rt2[fa[i]]=merge2(rt2[fa[i]],rt2[i],1,n,fa[i]);
    69     }
    70     for(int i=1;i<=m;i++)
    71     {
    72         int x,d;scanf("%d%d",&x,&d);
    73         x^=ans,d^=ans;
    74         ans=query(rt1[x],1,n,deep[x],min(deep[x]+d,n));
    75         printf("%d
    ",ans);
    76     }
    77 }
    78 int main()
    79 {
    80     scanf("%d",&T);
    81     while(T--) work();
    82     return 0;
    83 }
  • 相关阅读:
    运算符
    javaScript注意事项
    初识JavaScript.
    tomee.xml
    setenv.bat
    catalina.properties
    tomee 系列问题
    tomee 第一个 远程调用 Message-driven bean(MDB)
    tomee 第一个 远程调用 Session Bean
    Java EE 参考文档及sample
  • 原文地址:https://www.cnblogs.com/Slrslr/p/10014768.html
Copyright © 2020-2023  润新知