• [HDU5709]Claris Loves Painting


    description

    vjudge
    给定一棵(n)点的树,每个节点上有一个颜色,每次询问一个点的子树中与这个点距离不超过(d)的点的颜色有多少种。强制在线。
    ——本题面描述转载租酥雨的博客,版权所有,仿冒必究

    data range

    [sum n,sum mle 5 imes 10^5 ]

    solution

    考虑线段树合并。
    首先想到维护深度的线段树,处理出每个节点对应深度最前的颜色有多少个。
    合并时可能会算重,如果直接维护不知道颜色的重复情况,
    所以还要维护一棵颜色的线段树,记录每个颜色的最浅深度
    因为这里的每一棵线段树都要用于查询,因此合并时不能向主席树那样直接指儿子,而要新建节点

    复杂度(O(nlogn))

    Code

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cassert>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define FL "a"
    #define fi first
    #define se second
    #define RG register
    using namespace std;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-6;
    const int mod=1e4;
    const int N=4e5+10;
    const int M=4e5+10;
    const dd pi=acos(-1);
    const int inf=2147483647;
    const ll INFL=1e18+1;
    const ll P=100000;
    inline ll read(){
      RG ll data=0,w=1;RG char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
      if(ch=='-')w=-1,ch=getchar();
      while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
      return data*w;
    }
    inline void file(){
      srand(time(NULL)+rand());
      freopen(FL".in","r",stdin);
      freopen(FL".out","w",stdout);
    }
    
    int n,m,c[N],ans;
    int head[N],nxt[N<<1],to[N<<1],cnt;
    inline void add(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;}
    
    int drt[N],ds[2][20*N],sz[20*N],dtot;
    #define mid ((l+r)>>1)
    void dinsert(int &i,int l,int r,int p,int v){//sum of colors
      int x=++dtot;ds[0][x]=ds[0][i];ds[1][x]=ds[1][i];sz[x]=sz[i]+v;i=x;
      if(l==r)return;
      p<=mid?dinsert(ds[0][i],l,mid,p,v):dinsert(ds[1][i],mid+1,r,p,v);
    }
    int query(int i,int l,int r,int x,int y){
      if(!i||x>y)return 0;if(x<=l&&r<=y)return sz[i];int v=0;
      if(x<=mid)v=query(ds[0][i],l,mid,x,y);
      if(mid<y)v+=query(ds[1][i],mid+1,r,x,y);
      return v;
    }
    int dmerge(int a,int b){
      if(!a||!b)return a|b;int c=++dtot;
      ds[0][c]=dmerge(ds[0][a],ds[0][b]);
      ds[1][c]=dmerge(ds[1][a],ds[1][b]);
      sz[c]=sz[a]+sz[b];return c;
    }
    
    int crt[N],cs[2][20*N],mn[20*N],ctot;
    void cinsert(int &i,int l,int r,int p,int v){//mindep of color
      if(!i){i=++ctot;mn[i]=inf;cs[0][i]=cs[1][i]=0;}
      mn[i]=min(mn[i],v);if(l==r)return;
      p<=mid?cinsert(cs[0][i],l,mid,p,v):cinsert(cs[1][i],mid+1,r,p,v);
    }
    int cmerge(int a,int b,int l,int r,int u){
      if(!a||!b)return a|b;int c=++ctot;
      if(l==r){
        dinsert(drt[u],1,n,max(mn[a],mn[b]),-1);
        mn[c]=min(mn[a],mn[b]);cs[0][c]=cs[1][c]=0;
      }
      else{
        cs[0][c]=cmerge(cs[0][a],cs[0][b],l,mid,u);
        cs[1][c]=cmerge(cs[1][a],cs[1][b],mid+1,r,u);
        mn[c]=min(mn[cs[0][c]],mn[cs[1][c]]);
      }
      return c;
    }
    
    int dep[N];
    void dfs(int u){
      for(RG int i=head[u];i;i=nxt[i]){
        RG int v=to[i];dfs(v);
        crt[u]=cmerge(crt[u],crt[v],1,n,u);
        drt[u]=dmerge(drt[u],drt[v]);
      }
    }
    
    int main()
    {
      int T=read();
      while(T--){
        n=read();m=read();
        ans=ctot=dtot=cnt=0;dep[1]=1;mn[0]=inf;
        for(RG int i=1;i<=n;i++)head[i]=crt[i]=drt[i]=0,c[i]=read();
        for(RG int i=2,fa;i<=n;i++)fa=read(),add(fa,i),dep[i]=dep[fa]+1;
        for(RG int i=1;i<=n;i++){
          dinsert(drt[i],1,n,dep[i],1);
          cinsert(crt[i],1,n,c[i],dep[i]);
        }
        dfs(1);
        for(RG int i=1,u,d;i<=m;i++){
          u=read()^ans;d=dep[u]+(read()^ans);
          ans=query(drt[u],1,n,1,min(d,n));printf("%d
    ",ans);
        }
      }
      return 0;
    }
    
    
  • 相关阅读:
    省市县区镇街道可查询地址
    用代码实现表情包
    如何让input number类型的标签不产生上下加减的按钮
    float类型如何转换为string类型
    php 如何得到不含前导0的时分秒
    项目引入非配置的文件,打成war包后测试报错的可能原因
    Spring Cloud(十四)Config 配置中心与客户端的使用与详细
    Spring Cloud (十三) Zuul:静态路由、静态过滤器与动态路由的实现
    Spring Cloud(十二)声名式服务调用:Feign 的使用(下)
    Spring Cloud(十一)声名式服务调用:Feign的使用 (上)
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9919326.html
Copyright © 2020-2023  润新知