【树链剖分】【动态开点线段树】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 }