【ZJOI2008】【link-cut tree】树的统计

来源:互联网 发布:天池竞赛用什么算法 编辑:程序博客网 时间:2024/06/04 01:13

这道题写了比较。。。主要是手残比较多

关键的一点是由于题目直接给出了树的每条边,所以建树要用dfs来建,我最开始使用access(x)然后pre[x] = y的方法要WA,不过我感觉这样做是对的。。。当然这种感觉上对的方法不但是错的,而且效率肯定不如dfs

其他的就是动态树的基本操作了,没什么好说的。

代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 30000 + 10;const int maxm = 100000;const int inf = 0x3f3f3f3f;struct pnode{int pos;pnode *next;pnode(){}pnode(int pos,pnode *next):pos(pos),next(next){}}*first[maxn], __[maxm],*tot = __;int ch[maxn][2],pre[maxn];int sum[maxn],Max[maxn],w[maxn];bool rev[maxn];int n,m;void init(){freopen("count.in","r",stdin);freopen("count.out","w",stdout);}void update(int x){sum[x] = sum[ ch[x][0] ] + sum[ ch[x][1] ] + w[x];Max[x] = max(w[x],max(Max[ ch[x][0] ],Max[ ch[x][1] ]));if(rev[x]){swap(ch[x][0],ch[x][1]);rev[ ch[x][0] ] = !rev[ ch[x][0] ];rev[ ch[x][1] ] = !rev[ ch[x][1] ];rev[x] = false;}}bool isroot(int x){return ch[pre[x]][0] != x && ch[pre[x]][1] != x;}void push_down(int x){if(!isroot(x))push_down(pre[x]);update(x);}void rotate(int x,int f){int y = pre[x],z = pre[y];ch[y][!f] = ch[x][f];pre[ ch[x][f] ] = y;pre[x] = pre[y];if(ch[z][0] == y)ch[z][0] = x;else if(ch[z][1] == y)ch[z][1] = x;pre[y] = x;ch[x][f] = y;update(y);}void splay(int x){push_down(x);while(!isroot(x)){if(isroot(pre[x]))rotate(x,ch[pre[x]][0] == x);else{int y = pre[x],z = pre[y];int f = (ch[z][0] == y);if(ch[y][f] == x)rotate(x,!f),rotate(x,f);else rotate(y,f),rotate(x,f);}}update(x);}void access(int u){for(int v = 0;u;v = u,u = pre[u]){splay(u);ch[u][1] = v;update(u);}}void evert(int x){access(x);splay(x);rev[x] = !rev[x];}void link(int a,int b){evert(a);pre[a] = b;update(a);}int query(int x,int y,bool flag){access(y);for(y = 0;x;y = x,x = pre[x]){splay(x);if(!pre[x]){if(!flag)return max(w[x],max(Max[ch[x][1]],Max[y]));else return sum[ch[x][1]] + sum[y] + w[x];}ch[x][1] = y;update(x);}return 0;}void modify(int t,int key){w[t] = key;splay(t);}void dfs(int u,int f){for(pnode *p = first[u];p != NULL;p = p -> next){int v = p -> pos;if(v == f)continue;dfs(v,u);pre[v] = u;}}void readdata(){memset(Max,~0x3f,sizeof(Max));memset(ch,0,sizeof(ch));memset(rev,false,sizeof(rev));scanf("%d",&n);for(int i = 1;i < n;i++){int u,v;scanf("%d%d",&u,&v);first[u] = new(tot++)pnode(v,first[u]);first[v] = new(tot++)pnode(u,first[v]);}for(int i = 1;i <= n;i++)scanf("%d",&w[i]);w[0] = Max[0] = -inf;dfs(1,0);scanf("%d",&m);for(int i = 1;i <= m;i++){char op[10];int a,b;scanf("%s%d%d",op,&a,&b);if(!strcmp(op,"QMAX"))printf("%d\n",query(a,b,0));if(!strcmp(op,"QSUM"))printf("%d\n",query(a,b,1));if(!strcmp(op,"CHANGE"))modify(a,b);}}int main(){init();readdata();return 0;}