[bzoj] 1036: [ZJOI2008]树的统计Count 发表于 Apr 6 2015 | 分类于 bzoj | 题意单点修改,链查询max,sum 分析裸体不说了 代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150/****************************************\* Author : ztx* Title : [bzoj] 1036: [ZJOI2008]树的统计Count* ALG : LCT复习 平衡树写的spaly* CMT :单点修改,链查询max,sum* Time :\****************************************/#include <cstdio>#define Rep(i,l,r) for(i=(l);i<=(r);i++)#define Rev(i,r,l) for(i=(r);i>=(l);i--)typedef long long ll ;int CH , NEG ;template <typename TP>inline void read(TP& ret) { ret = NEG = 0 ; while (CH=getchar() , CH<'!') ; if (CH == '-') NEG = true , CH = getchar() ; while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ; if (NEG) ret = -ret ;}template <typename TP>inline void reads(TP& ret) {truewhile (ret=getchar() , ret<'!') ;truewhile (ret=CH,CH=getchar() , CH>'!') ;}#define maxn 30010LLint fa[maxn] = {0} , ch[maxn][2] = {0} ;int val[maxn] = {0} , maxv[maxn] = {0} , sumv[maxn] = {0} ;bool rev[maxn] = {0} ;#define null 0LL#define left(u) ch[u][0]#define right(u) ch[u][1]inline void Exchange(int&a,int&b) {int c=a;a=b;b=c;}inline bool Isrt(int u) { return !fa[u] || (left(fa[u])!=u&&right(fa[u])!=u) ; }inline void Clear(int u) {trueif (!u) return ;trueif (rev[u]) {truetruerev[u] = false ;truetrueExchange(left(u),right(u)) ;truetruerev[left(u)] ^= true ;truetruerev[right(u)] ^= true ;true}}inline void Maintain(int u) {trueif (!u) return ;truesumv[u] = maxv[u] = val[u] ;trueif (left(u)) {truetruesumv[u] += sumv[left(u)] ;truetrueif (maxv[left(u)] > maxv[u]) maxv[u] = maxv[left(u)] ;true}trueif (right(u)) {truetruesumv[u] += sumv[right(u)] ;truetrueif (maxv[right(u)] > maxv[u]) maxv[u] = maxv[right(u)] ;true}}inline void Rot(int x , int d) {trueint y = fa[x] , z = fa[y] ;trueif (left(z)==y) left(z) = x ;trueelse if (right(z)==y) right(z) = x ;truefa[x] = z , fa[ch[x][d]] = y , ch[y][!d] = ch[x][d] ;truech[x][d] = y , fa[y] = x ;trueMaintain(y) ;}/*inline void Spaly(int x) {trueClear(x) ;truewhile (!Isrt(x))truetrueClear(fa[x]),Clear(x),Rot(x,ch[fa[x]][0]==x) ;trueMaintain(x) ;}//有人说上面单旋应该叫做Spaly,下面是双旋,是真的Splay*/inline void Spaly(int x){trueint y , z ;trueClear(x) ;truewhile (!Isrt(x)) {truetruey = fa[x] , z = fa[y] ;truetrueClear(z) , Clear(y) , Clear(x) ;truetrueif (Isrt(y)) Rot(x,ch[y][0]==x) ;truetrueelse if(ch[z][0] == y) {truetruetrueif (ch[y][0] == x) Rot(y,1) ;truetruetrueelse Rot(x,0) ; Rot(x,1) ;truetrue} else {truetruetrueif(ch[y][1] == x) Rot(y,0) ;truetruetrueelse Rot(x,1) ; Rot(x,0) ;truetrue}true}trueMaintain(x) ;}inline void Access(int u) {truefor (int v=null ; u ; v=u,u=fa[u]) Spaly(u), right(u)=v, Maintain(u) ;}inline void MakeRoot(int u) {trueAccess(u) , Spaly(u) , rev[u] ^= true ;}inline void ChainMax(int u , int v) {trueMakeRoot(u) , Access(v) , Spaly(v) ;trueprintf("%d\n", maxv[v]) ;}inline void ChainSum(int u , int v) {trueMakeRoot(u) , Access(v) , Spaly(v) ;trueprintf("%d\n", sumv[v]) ;}inline void NodeChange(int u , int v) {trueSpaly(u) ; val[u] = v ; Maintain(u) ;}#define maxm 30010LLstruct FST { int to , next ; } e[maxm<<1] ;int star[maxn] = {0} , tote = 1 ;inline void AddEdge(int u , int v) { e[++tote].to = v ; e[tote].next = star[u] ; star[u] = tote ; }inline void GetPar(int u) {truefor (int p=star[u] ; p ; p=e[p].next)truetrueif (e[p].to != fa[u])truetruetruefa[e[p].to] = u , GetPar(e[p].to) ;}int main() {int n , m , i , u , v , cmd ;true#define READtrue#ifdef READtruetruefreopen("bzoj_1036.in" ,"r",stdin ) ;truetruefreopen("bzoj_1036.out","w",stdout) ;true#endiftrueread(n) ;trueRep (i,2,n)truetrueread(u) , read(v) ,truetrueAddEdge(u,v) , AddEdge(v,u) ;trueRep (i,1,n)truetrueread(val[i]) , maxv[i] = sumv[i] = val[i] ;trueGetPar(1) ;trueread(m) ;truewhile (m --> 0) {truetruereads(cmd) , read(u) , read(v) ;truetrueif (cmd == 'E') NodeChange(u,v) ;truetrueif (cmd == 'X') ChainMax(u,v) ;truetrueif (cmd == 'M') ChainSum(u,v) ;true}true#ifdef READtruetruefclose(stdin) ; fclose(stdout) ;true#elsetruetruegetchar() ; getchar() ;true#endiftruereturn 0 ;}