BZOJ1037 ZJOI2008 树的统计 树链剖分
题意:给定一棵树,维护:1、将u的权值修改为v 2、求u到v路径上的最大权 3、求u到v路径上的点权和
题解:树链剖分裸题
#include <cstdio> #include <climits> #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[2*MAXN]; struct NODE{ int v,son,f,c,depth,belong,mark; HASH *child; }node[MAXN]; typedef struct TREE{ int v,s,l,r,same; TREE *lchild,*rchild; TREE(){} TREE(int _l,int _r):l(_l),r(_r),s(0),same(INT_MIN),lchild(0),rchild(0){} } *ROOT; ROOT root; int N,Q,cnt,mark[MAXN]; char s[8+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[x].son || node[p->u].c>node[node[x].son].c) node[x].son=p->u; } } void DFS2(int x,int b){ node[x].belong=b,node[x].mark=++cnt,mark[cnt]=x; 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].f && p->u!=node[x].son) DFS2(p->u,p->u); } void Pushup(ROOT &x){ x->s=x->lchild->s+x->rchild->s; x->v=max(x->lchild->v,x->rchild->v); } void Pushdown(ROOT &x,int m){ if(x->same!=INT_MIN){ x->lchild->v=x->rchild->v=x->same; x->lchild->same=x->rchild->same=x->same; x->lchild->s=x->same*(m-(m>>1)); x->rchild->s=x->same*(m>>1); x->same=INT_MIN; } } void Build(ROOT &x,int l,int r){ x=new TREE(l,r); if(l==r){ x->s=x->v=node[mark[l]].v; return; } int m=(l+r)>>1; Build(x->lchild,l,m),Build(x->rchild,m+1,r); Pushup(x); } void Change(ROOT &x,int p,int v){ if(x->l==x->r){ x->v=x->same=v,x->s=v*(x->r-x->l+1); return; } Pushdown(x,x->r-x->l+1); int m=(x->l+x->r)>>1; if(p<=m) Change(x->lchild,p,v); else Change(x->rchild,p,v); Pushup(x); } int Find_Max(ROOT &x,int l,int r){ if(x->l>=l && x->r<=r) return x->v; Pushdown(x,x->r-x->l+1); int m=(x->l+x->r)>>1,ret=INT_MIN; 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 Get_Max(int u,int v){ int ret=INT_MIN; 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,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,node[v].mark,node[u].mark)); return ret; } int Find_Sum(ROOT &x,int l,int r){ if(x->l>=l && x->r<=r) return x->s; Pushdown(x,x->r-x->l+1); 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 Get_Sum(int u,int v){ int ret=0; 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,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,node[v].mark,node[u].mark); return ret; } int main(){ memset(node,0,sizeof(node)); cnt=0; cin >> N; for(int i=1,u,v;i<N;i++){ cin >> u >> v; Insert(u,v),Insert(v,u); } for(int i=1;i<=N;i++) cin >> node[i].v; cnt=0,DFS1(1,0,0),DFS2(1,1); Build(root,1,cnt); cin >> Q; for(int i=1,a,b;i<=Q;i++){ scanf("%s %d %d",s,&a,&b); if(strstr(s,"QMAX")) cout << Get_Max(a,b) << endl; if(strstr(s,"QSUM")) cout << Get_Sum(a,b) << endl; if(strstr(s,"CHANGE")) Change(root,node[a].mark,b); } return 0; }