BZOJ3531 SDOI2014 旅行 树链剖分
题意:给定一棵树,维护:1、将u的种类改为c 2、将u的权值改为w 3、求u到v路径上种类为c的点的点权和 4、求u到v路径上种类为c的点的最大点权
题解:每个宗教建一颗线段树,然后随便做……考虑到如果把每一棵线段树都建完全会MLE,所以我们开动态内存。因为给出的评级都是正整数,所以如果一个区间的和为0,delete掉
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int MAXN=100000+2; struct HASH{ int u; HASH *next; HASH(){} HASH(int _u,HASH *_next):u(_u),next(_next){} }mem[MAXN*2]; struct NODE{ int v,f,c,son,col,mark,depth,belong; HASH *child; }node[MAXN]; typedef struct TREE{ int l,r,s,maximum; TREE *lchild,*rchild; TREE(){} TREE(int _l,int _r):l(_l),r(_r),lchild(0),rchild(0){} } *ROOT; ROOT root[MAXN]; int N,Q,cnt; char s[6+2]; void Insert(int u,int v){ node[u].child=&(mem[cnt++]=HASH(v,node[u].child));} void DFS1(int x,int f,int d){ node[x].f=f,node[x].depth=d,node[x].c=1; for(HASH *p=node[x].child;p;p=p->next) if(p->u!=f){ DFS1(p->u,x,d+1); node[x].c+=node[p->u].c; if(node[node[x].son].c<node[p->u].c) node[x].son=p->u; } } void DFS2(int x,int b){ node[x].belong=b,node[x].mark=++cnt; if(!node[x].son) return; DFS2(node[x].son,b); for(HASH *p=node[x].child;p;p=p->next) if(p->u!=node[x].son && p->u!=node[x].f) DFS2(p->u,p->u); } void Pushup(ROOT &x){ x->s=x->maximum=0; if(x->lchild) x->s+=x->lchild->s,x->maximum=max(x->maximum,x->lchild->maximum); if(x->rchild) x->s+=x->rchild->s,x->maximum=max(x->maximum,x->rchild->maximum); } void Update(ROOT &x,int l,int r,int p,int v){ if(!x) x=new TREE(l,r); if(l==r){ if(!v) delete x,x=0; else x->s=x->maximum=v; return; } int m=(l+r)>>1; if(p<=m) Update(x->lchild,l,m,p,v); else Update(x->rchild,m+1,r,p,v); Pushup(x); if(!x->s) delete x,x=0; } int Find_Sum(ROOT &x,int l,int r){ if(!x) return 0; if(x->l>=l && x->r<=r) return x->s; int m=(x->l+x->r)>>1,ret=0; if(l<=m) ret+=Find_Sum(x->lchild,l,r); if(r>m) ret+=Find_Sum(x->rchild,l,r); return ret; } int Query_Sum(int u,int v){ int ret=0,col=node[u].col; while(node[u].belong!=node[v].belong){ if(node[node[u].belong].depth<node[node[v].belong].depth) swap(u,v); ret+=Find_Sum(root[col],node[node[u].belong].mark,node[u].mark); u=node[node[u].belong].f; } if(node[u].depth<node[v].depth) swap(u,v); ret+=Find_Sum(root[col],node[v].mark,node[u].mark); return ret; } int Find_Max(ROOT &x,int l,int r){ if(!x) return -1; if(x->l>=l && x->r<=r) return x->maximum; int m=(x->l+x->r)>>1,ret=-1; if(l<=m) ret=max(ret,Find_Max(x->lchild,l,r)); if(r>m) ret=max(ret,Find_Max(x->rchild,l,r)); return ret; } int Query_Max(int u,int v){ int ret=-1,col=node[u].col; while(node[u].belong!=node[v].belong){ if(node[node[u].belong].depth<node[node[v].belong].depth) swap(u,v); ret=max(ret,Find_Max(root[col],node[node[u].belong].mark,node[u].mark)); u=node[node[u].belong].f; } if(node[u].depth<node[v].depth) swap(u,v); ret=max(ret,Find_Max(root[col],node[v].mark,node[u].mark)); return ret; } int main(){ memset(node,0,sizeof(node)); scanf("%d %d",&N,&Q); for(int i=1;i<=N;i++) scanf("%d %d",&node[i].v,&node[i].col); for(int i=1,u,v;i<N;i++){ scanf("%d %d",&u,&v); Insert(u,v),Insert(v,u); } cnt=0,DFS1(1,0,0),DFS2(1,1); for(int i=1;i<=N;i++) Update(root[node[i].col],1,N,node[i].mark,node[i].v); for(int i=1,x,y,v;i<=Q;i++){ scanf("%s %d %d",s,&x,&y); if(strstr(s,"CC")){ v=Find_Sum(root[node[x].col],node[x].mark,node[x].mark); Update(root[node[x].col],1,N,node[x].mark,0); node[x].col=y; Update(root[node[x].col],1,N,node[x].mark,v); } if(strstr(s,"CW")) Update(root[node[x].col],1,N,node[x].mark,y); if(strstr(s,"QS")) printf("%d\n",Query_Sum(x,y)); if(strstr(s,"QM")) printf("%d\n",Query_Max(x,y)); } return 0; }