NKOJ2250 树的统计
时间限制 : 20000 MS 空间限制 : 265536 KB
问题描述
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
1.CHANGE u t : 把结点u的权值改为t
2.QMAX u v: 询问从点u到点v的路径上的节点的最大权值
3.QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
输入格式
第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出格式
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
样例输入
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
样例输出
4
1
2
2
10
6
5
6
5
16
提示
对于100%的数据,保证1<=n<=30000,0<=q<=200000;
中途操作中保证每个节点的权值w在-30000到30000之间。
来源 【ZJOI2008】
思路:动态树…..
注意:
权值可能为负….
各点在link前视为森林,仍要保持各点存储信息的正确性
#include<cstdio>
#include<iostream>
using namespace std;
const int need=30004;
//..........................................
inline void inc(char &t)
{
t=getchar();
while(t==10||t==' '||t=='Q') t=getchar();
}
inline void in_(int &d)
{
char t=getchar();bool mark=0;
while(t<'0'||t>'9') {if(t=='-') mark=1;t=getchar();}
for(d=0;!(t<'0'||t>'9');t=getchar()) d=(d<<1)+(d<<3)+t-'0';
if(mark) d=-d;
}
inline void out_(int x)
{
if(x<0) {x=-x;putchar('-');}
if(x>=10) out_(x/10);
putchar(x%10+'0');
}
//..........................................
int ls[need],rs[need],fa[need],val[need],sum[need],maxx[need];
bool lazy[need];
#define isroot(x) ((!(ls[fa[x]]==x||rs[fa[x]]==x))||fa[x]==0)
inline void NBHB(int x)
{
sum[x]=maxx[x]=val[x];
if(ls[x]) sum[x]+=sum[ls[x]],maxx[x]=max(maxx[ls[x]],maxx[x]);
if(rs[x]) sum[x]+=sum[rs[x]],maxx[x]=max(maxx[rs[x]],maxx[x]);
}
inline void putdown(int x)
{
lazy[x]=0;
swap(ls[x],rs[x]);
if(ls[x]) lazy[ls[x]]^=1;
if(rs[x]) lazy[rs[x]]^=1;
}
int sss[need],tops;
void super_putdown(int x)
{
sss[tops=1]=x;
while(!isroot(x)) sss[++tops]=(x=fa[x]);
for(;tops;tops--) if(lazy[sss[tops]]) putdown(sss[tops]);
}
inline void rotate(int x,int mm)
{
int y=fa[x],z=fa[y];
if(lazy[z]) putdown(z);
if(lazy[y]) putdown(y);
if(lazy[x]) putdown(x);
if(!isroot(y)) ls[z]==y ? ls[z]=x :rs[z]=x;
fa[x]=z;
if(mm==1)
{
ls[y]=rs[x]; fa[rs[x]]=y;
rs[x]=y; fa[y]=x;
}
else
{
rs[y]=ls[x]; fa[ls[x]]=y;
ls[x]=y; fa[y]=x;
}
NBHB(y),NBHB(x);
}
void splay(int x)
{
super_putdown(x);
while(!isroot(x))
{
if(ls[fa[x]]==x) rotate(x,1);
else rotate(x,2);
}
}
void join(int x)
{
for(int t=0;x;t=x,x=fa[x])
splay(x),rs[x]=t,NBHB(x);
}
#define setroot(x) join(x),splay(x),lazy[x]^=1
#define link(x,y) setroot(x),fa[x]=y
//..........................................
int aa[need],bb[need];
//..........................................
int main()
{
int n;in_(n);
for(int a,b,i=1;i<n;i++) in_(aa[i]),in_(bb[i]);
for(int i=1;i<=n;i++) in_(val[i]),sum[i]=maxx[i]=val[i];
for(int i=1;i<n;i++) link(aa[i],bb[i]);//先更新各节点的值再link
int m;in_(m);
char c;int a,b;
while(m--)
{
inc(c),in_(a),in_(b);
if(c=='C')
{
setroot(a);
val[a]=b;
NBHB(a);
}
else
{
setroot(a);
join(b);
splay(b);
if(c=='S') out_(sum[b]),putchar(10);
else out_(maxx[b]),putchar(10);
}
}
}