【树链剖分】【动态开点线段树】bzoj3531 旅行

每种信仰存一个线段树

 动态开点线段树就是点 现用现开 所以要存左右儿子

一次询问最多新建logn节点 

空间复杂度 m*logn

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 const int N=100000+5;
  5 int n,w[N],c[N];
  6  
  7 int num,last[N],nxt[2*N],ver[2*N];
  8 inline void add(int x,int y) {nxt[++num]=last[x]; last[x]=num; ver[num]=y;}
  9  
 10 int fa[N],sum[N],deep[N],son[N];
 11 void build(int x)
 12  {sum[x]=1;
 13   for(int i=last[x];i;i=nxt[i])
 14    {int y=ver[i];
 15     if(y==fa[x]) return;
 16     fa[y]=x; deep[y]=deep[x]+1;
 17     build(y);
 18     sum[x]+=sum[y];
 19     if(sum[son[x]]<sum[y]) son[x]=y;
 20    }
 21  }
 22  
 23 int id,a[N],ord[N],top[N];
 24 void dfs(int x)
 25  {a[++id]=x; ord[x]=id;
 26    
 27   if(x==son[fa[x]]) top[x]=top[fa[x]];
 28   else              top[x]=x;
 29    
 30   if(son[x]) dfs(son[x]);
 31   for(int i=last[x];i;i=nxt[i])
 32    {int y=ver[i];
 33     if(y==fa[x] || y==son[x]) continue;
 34     dfs(y);
 35    }
 36  } 
 37  
 38 struct point{int ls,rs,maxx,sum;}t[20*N]; int tot,root[N];
 39  
 40 void change(int &i,int l,int r,int pos,int x)
 41  {if(!i) i=++tot;
 42   if(l==r) {t[i].sum=t[i].maxx=x; return;}
 43    
 44   int mid=(l+r)/2;
 45   if(pos<=mid) change(t[i].ls,l,mid,pos,x);
 46   else         change(t[i].rs,mid+1,r,pos,x);
 47    
 48   t[i].sum=t[t[i].ls].sum+t[t[i].rs].sum;
 49   t[i].maxx=max(t[t[i].ls].maxx,t[t[i].rs].maxx);
 50  }
 51   
 52 point ask(int &i,int l,int r,int p,int q)
 53  {if(!i) return t[tot+1];
 54   if(p<=l && r<=q) return t[i];
 55   int mid=l+r>>1;
 56   if(q<=mid) return ask(t[i].ls,l,mid,p,q);
 57   if(p> mid) return ask(t[i].rs,mid+1,r,p,q);
 58    
 59       point r1=ask(t[i].ls,l,mid,p,q),r2=ask(t[i].rs,mid+1,r,p,q);
 60       r1.sum=r1.sum+r2.sum;
 61       r1.maxx=max(r1.maxx,r2.maxx);
 62       return r1;
 63  } 
 64 inline point query(int x,int y,int z)
 65   {point re; re.sum=re.maxx=0;
 66    while(top[x]!=top[y])
 67     {if(deep[top[x]]<deep[top[y]]) swap(x,y);
 68      point k=ask(z,1,n,ord[top[x]],ord[x]); 
 69      re.sum+=k.sum;
 70      re.maxx=max(re.maxx,k.maxx);
 71       
 72      x=fa[top[x]];
 73     }
 74    if(deep[x]<deep[y]) swap(x,y);
 75      point k=ask(z,1,n,ord[y],ord[x]); 
 76      re.sum+=k.sum;
 77      re.maxx=max(re.maxx,k.maxx);
 78     return re; 
 79   } 
 80 int main()
 81 {
 82  int q,x,y;
 83  scanf("%d%d",&n,&q);
 84  for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]);
 85  
 86  for(int i=1;i<n;i++) {scanf("%d%d",&x,&y); add(x,y); add(y,x);}
 87  
 88  deep[1]=1; build(1);  dfs(1);
 89  for(int i=1;i<=n;i++) change(root[c[i]],1,n,ord[i],w[i]);
 90   
 91  while(q--)
 92   { char op[5]; scanf("%s %d%d",op,&x,&y); 
 93     if(op[1]=='C')
 94               { change(root[c[x]],1,n,ord[x],0);
 95                 change(root[y],1,n,ord[x],w[x]);
 96                 c[x]=y;
 97               }
 98     else if(op[1]=='W')
 99               { change(root[c[x]],1,n,ord[x],y);
100                 w[x]=y;
101               }
102     else if(op[1]=='S')
103               {point ans=query(x,y,root[c[y]]);
104                printf("%d\n",ans.sum);
105               }
106     else if(op[1]=='M')
107               {point ans=query(x,y,root[c[y]]);
108                printf("%d\n",ans.maxx);
109               }
110   }
111 return 0;
112 }

 


 

posted @ 2018-09-23 16:25  YuXiaoze  阅读(123)  评论(0编辑  收藏  举报