bzoj1036
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14796 Solved: 5991
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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
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
1
2
2
10
6
5
6
5
16
HINT
Source
lct练习题。错误:一定要先把初始点权算好再连边。。。这也是错误
晚上不能松懈啊,要有明确的的计划!
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; #define N 300010 int n,q; int fa[N],tag[N],st[N],key[N],u[N],v[N]; ll mx[N],sum[N]; int child[N][2]; ll max(ll x,ll y) { return x>y?x:y; } void update(int x) { sum[x]=sum[child[x][0]]+sum[child[x][1]]+key[x]; mx[x]=max(key[x],max(mx[child[x][0]],mx[child[x][1]])); } bool isroot(int x) { return (!fa[x]||(child[fa[x]][0]!=x&&child[fa[x]][1]!=x)); } void pushdown(int x) { if(!tag[x]) return; tag[x]^=1; swap(child[x][0],child[x][1]); tag[child[x][0]]^=1; tag[child[x][1]]^=1; } void zig(int x) { int y=fa[x]; fa[x]=fa[y]; if(!isroot(y)) child[fa[x]][child[fa[x]][1]==y]=x; child[y][0]=child[x][1]; fa[child[x][1]]=y; fa[y]=x; child[x][1]=y; update(y); update(x); } void zag(int x) { int y=fa[x]; fa[x]=fa[y]; if(!isroot(y)) child[fa[x]][child[fa[x]][1]==y]=x; child[y][1]=child[x][0]; fa[child[x][0]]=y; fa[y]=x; child[x][0]=y; update(y); update(x); } void splay(int x) { int top=0; st[++top]=x; for(int y=x;!isroot(y);y=fa[y]) st[++top]=fa[y]; for(int i=top;i;i--) pushdown(st[i]); while(!isroot(x)) { int y=fa[x],z=fa[y]; if(isroot(y)) { child[y][0]==x?zig(x):zag(x); break; } child[y][0]==x?zig(x):zag(x); child[z][0]==x?zig(x):zag(x); } } void access(int x) { for(int t=0;x;t=x,x=fa[x]) { splay(x); child[x][1]=t; update(x); } } void rever(int x) { access(x); splay(x); tag[x]^=1; } void link(int u,int v) { rever(u); fa[u]=v; } void change(int u,int v) { key[u]=v; update(u); splay(u); } void querymax(int u,int v) { rever(u); access(v); splay(v); printf("%lld\n",mx[v]); } void querysum(int u,int v) { rever(u); access(v); splay(v); printf("%lld\n",sum[v]); } int main() { memset(mx,-0x3f3f,sizeof(mx)); scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d%d",&u[i],&v[i]); } for(int i=1;i<=n;i++) { scanf("%d",&key[i]); update(i); } for(int i=1;i<n;i++) link(u[i],v[i]); scanf("%d",&q); while(q--) { char s[10]; scanf("%s",s); if(s[1]=='M') { int u,v; scanf("%d%d",&u,&v); querymax(u,v); } if(s[1]=='S') { int u,v; scanf("%d%d",&u,&v); querysum(u,v); } if(s[1]=='H') { int u,v; scanf("%d%d",&u,&v); change(u,v); } } return 0; }