【JSOI2008】【BZOJ1036】【LCT版】树的统计Count

来源:互联网 发布:手机知乎怎么匿名回答 编辑:程序博客网 时间:2024/05/21 07:55

如今我终于来用LCT做这个题了QwQ

Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4

1 2

2 3

4 1

4 2 1 3

12

QMAX 3 4

QMAX 3 3

QMAX 3 2

QMAX 2 3

QSUM 3 4

QSUM 2 1

CHANGE 1 5

QMAX 3 4

CHANGE 3 6

QMAX 3 4

QMAX 2 4

QSUM 3 4
Sample Output

4

1

2

2

10

6

5

6

5

16
HINT

Source

树的分治

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define LL long long#define MAXN 50010#define MAXINT 0x7fffffffusing namespace std;struct splay{    int fa,ch[2];    LL sum,maxn,w;    bool rev;}tree[MAXN];int q[MAXN],top;char ch[10];void print();long long U,V,n,m,u[MAXN],v[MAXN];inline void in(long long &x){    int flag=1;char ch=getchar();x=0;    while (!(ch>='0'&&ch<='9')) flag=ch=='-'?-1:1,ch=getchar();    while (ch>='0'&&ch<='9')    x=x*10+ch-'0',ch=getchar();x*=flag;}inline bool is_root(int x){    return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;}inline void push_up(int x){    tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].w;    tree[x].maxn=max(tree[x].w,max(tree[tree[x].ch[0]].maxn,tree[tree[x].ch[1]].maxn));}inline void push_down(int x){    if (tree[x].rev)    {        tree[x].rev^=1;tree[tree[x].ch[0]].rev^=1;tree[tree[x].ch[1]].rev^=1;        swap(tree[x].ch[0],tree[x].ch[1]);    }}inline void rot(int x){    int y=tree[x].fa,z=tree[y].fa,l,r;    l=(tree[y].ch[1]==x);r=l^1;    if (!is_root(y))    tree[z].ch[(tree[z].ch[1]==y)]=x;    tree[tree[x].ch[r]].fa=y;tree[y].fa=x;tree[x].fa=z;    tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;    push_up(y);push_up(x);}inline void Splay(int x){    q[++top]=x;    for (int i=x;!is_root(i);i=tree[i].fa)  q[++top]=tree[i].fa;    while (top) push_down(q[top--]);    while (!is_root(x))    {        int y=tree[x].fa,z=tree[y].fa;        if (!is_root(y))        {            if (tree[y].ch[0]==x^tree[z].ch[0]==y)  rot(x);            else    rot(y);        }        rot(x);    }}inline void access(int x){    for (int t=0;x;t=x,x=tree[x].fa)    Splay(x),tree[x].ch[1]=t,push_up(x);}inline void make_root(int x){    access(x);Splay(x);tree[x].rev^=1;}inline void link(int x,int y){    make_root(x);tree[x].fa=y;}inline void cut(int x,int y){    make_root(x);access(y);Splay(y);}int main(){    in(n);tree[0].maxn=-MAXINT;    for (int i=1;i<n;i++)   in(u[i]),in(v[i]);    for (int i=1;i<=n;i++)  in(tree[i].w),tree[i].sum=tree[i].maxn=tree[i].w;    for (int i=1;i<n;i++)   link(u[i],v[i]);    in(m);    while (m--)    {        scanf("%s",ch);in(U);in(V);        if (ch[1]=='H') Splay(U),tree[U].w=V,push_up(U);        if (ch[1]=='M') cut(U,V),printf("%lld\n",tree[V].maxn);        if (ch[1]=='S') cut(U,V),printf("%lld\n",tree[V].sum);    }}
1 0
原创粉丝点击