zoukankan      html  css  js  c++  java
  • [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;
    }
    
    
  • 相关阅读:
    求子数组最大和
    layout_weight layout_width = 0dp
    一些日历的实现
    只显示年月日的日历
    每日学习之0512
    git 出现The current branch is not configured for pull No value for key branch.master.merge found in configuration错误的解决办法
    git的配置
    使用Spring security框架实现登陆页面时跳转到favicon.ico问题
    播放视频(c#)
    太阳沉落了
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9919326.html
Copyright © 2011-2022 走看看