zoukankan      html  css  js  c++  java
  • HDU5709 : Claris Loves Painting

    对于每个点维护两棵线段树$T1[x],T2[x]$:

    $T1[x]$维护$x$子树内,深度在$[l,r]$内的点数,同种颜色有多个的话,保留深度最小的那个。

    $T2[x]$维护$x$子树内每种颜色的最小深度。

    从底向上合并线段树,先合并$T1$,然后合并$T2$的时候,发现有重复点,那么在$T1$里删去深度大的那个,查询直接在$T1$里区间求和即可。

    时间复杂度$O((n+m)log n)$。

    #include<cstdio>
    const int N=100010,M=10000000;
    int Case,n,m,i,x,y,ans,a[N],f[N],d[N],T1[N],T2[N],tot,l[M],r[M],v[M];
    int ins(int x,int a,int b,int c,int p){
      int y=++tot;v[y]=v[x]+p;
      if(a==b)return y;
      int mid=(a+b)>>1;
      if(c<=mid)l[y]=ins(l[x],a,mid,c,p),r[y]=r[x];
      else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c,p);
      return y;
    }
    int merge1(int x,int y,int a,int b){
      if(!x||!y)return x+y;
      int z=++tot;
      v[z]=v[x]+v[y];
      if(a==b)return z;
      int mid=(a+b)>>1;
      l[z]=merge1(l[x],l[y],a,mid);
      r[z]=merge1(r[x],r[y],mid+1,b);
      return z;
    }
    int merge2(int x,int y,int a,int b,int p){
      if(!x||!y)return x+y;
      int z=++tot;
      if(a==b){
        if(v[x]<v[y])v[z]=v[x],T1[p]=ins(T1[p],1,n,v[y],-1);
        else v[z]=v[y],T1[p]=ins(T1[p],1,n,v[x],-1);
        return z;
      }
      int mid=(a+b)>>1;
      l[z]=merge2(l[x],l[y],a,mid,p);
      r[z]=merge2(r[x],r[y],mid+1,b,p);
      return z;
    }
    int ask(int x,int a,int b,int d){
      if(b<=d)return v[x];
      int mid=(a+b)>>1,t=ask(l[x],a,mid,d);
      if(d>mid)t+=ask(r[x],mid+1,b,d);
      return t;
    }
    int main(){
      scanf("%d",&Case);
      while(Case--){
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        for(i=2;i<=n;i++)scanf("%d",&f[i]);
        for(i=1;i<=n;i++)d[i]=d[f[i]]+1;
        for(i=1;i<=n;i++){
          T1[i]=ins(0,1,n,d[i],1);
          T2[i]=ins(0,1,n,a[i],d[i]);
        }
        for(i=n;i>1;i--){
          T1[f[i]]=merge1(T1[f[i]],T1[i],1,n);
          T2[f[i]]=merge2(T2[f[i]],T2[i],1,n,f[i]);
        }
        while(m--){
          scanf("%d%d",&x,&y);x^=ans,y^=ans;
          y+=d[x];
          if(y>n)y=n;
          printf("%d
    ",ans=ask(T1[x],1,n,y));
        }
        ans=tot=0;
      }
      return 0;
    }
    

      

  • 相关阅读:
    python encode 理解
    java类中的static代码块作用
    stanford 词性标注中词性的解释
    Stanford3.8.0依存句法分析在java中运行
    nginx和flask安装与配置
    docker使用
    docker安装
    哈工大分词安装及使用linux
    哈工大分词器中自定义词典的使用
    zookeeper集群安装
  • 原文地址:https://www.cnblogs.com/clrs97/p/5538804.html
Copyright © 2011-2022 走看看