您的位置:首页 > 其它

BZOJ1036 树的统计Count(LCT动态树)

2017-01-18 21:34 183 查看
一棵树上有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

Sample Output
4
1
2
2
10
6
5
6
5
16


LCT:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define F(x) tree[x].fa
#define LC(x) tree[x].child[0]
#define RC(x) tree[x].child[1]
#define REV(x) tree[x].rev
#define Size 300010
using namespace std;
inline int read(){
int sum=0,fg=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')fg=-1;c=getchar();}
while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
return sum*fg;
}
struct lct{
int fa,child[2],rev;
int v,sum,MAX;
}tree[Size];
struct link_cut_tree{
inline bool isroot(int x){
return LC(F(x))!=x && RC(F(x))!=x;
}
inline void pushup(int x){
tree[x].sum=tree[x].MAX=tree[x].v;
if(LC(x)){tree[x].sum+=tree[LC(x)].sum;tree[x].MAX=max(tree[x].MAX,tree[LC(x)].MAX);}
if(RC(x)){tree[x].sum+=tree[RC(x)].sum;tree[x].MAX=max(tree[x].MAX,tree[RC(x)].MAX);}
}
inline void pushdown(int x){
if(REV(x)){
REV(x)^=1;REV(LC(x))^=1;REV(RC(x))^=1;
swap(LC(x),RC(x));
}
}
void Pushdown(int x){
if(!isroot(x))Pushdown(F(x));
pushdown(x);
}
inline void rotate(int x){
int A=F(x),B=F(A);bool w=(RC(A)==x);
if(!isroot(A)){
if(LC(B)==A)LC(B)=x;
else if(RC(B)==A)RC(B)=x;
}
F(tree[x].child[w^1])=A;F(A)=x;F(x)=B;
tree[A].child[w]=tree[x].child[w^1];tree[x].child[w^1]=A;
pushup(A);pushup(x);
}
inline void splay(int x){
Pushdown(x);
while(!isroot(x)){
if(!isroot(F(x)))rotate(x);
rotate(x);
}
}
inline void access(int x){
for(int i=0;x;i=x,x=F(x)){splay(x),RC(x)=i,pushup(x);}
}
inline int find_root(int x){
access(x);splay(x);while(LC(x))x=LC(x);
return x;
}
inline void reverse(int x){
access(x);splay(x);REV(x)^=1;
}
inline void link(int x,int y){
reverse(x);F(x)=y;
}
inline void update(int x,int val){
tree[x].sum=tree[x].MAX=tree[x].v=val;
splay(x);pushup(x);
}
inline int query_max(int x,int y){
reverse(x);access(y);splay(y);
return tree[y].MAX;
}
inline int query_sum(int x,int y){
reverse(x);access(y);splay(y);
return tree[y].sum;
}
}LCT;
int main(){
int n=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
LCT.link(x,y);
}
for(int i=1;i<=n;i++){
int val=read();
LCT.update(i,val);
}
int m=read();
while(m--){
static char tp[10];
scanf("%s",tp);
if(tp[0]=='C'){
int x=read(),val=read();
LCT.update(x,val);
}
else if(tp[1]=='M'){
int x=read(),y=read();
printf("%d\n",LCT.query_max(x,y));
}
else{
int x=read(),y=read();
printf("%d\n",LCT.query_sum(x,y));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: