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
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
以前觉得树链剖分很高端。。结果现在很轻松就可以写出来。
要学习树链剖分的看下面那个链接吧
http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
【一开始用的cin读入string,结果一直在RE。后来改成scanf("%c",&x)一个个入读才过】
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct line
{
int s,t;
int next;
}a[100001];
int edge;
int head[100001];
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
struct tree
{
int l,r;
int s,max;
}tr[800001];
inline int max(int x,int y)
{
if(x>y)
return x;
return y;
}
inline void up(int p)
{
tr[p].max=max(tr[p*2].max,tr[p*2+1].max);
tr[p].s=tr[p*2].s+tr[p*2+1].s;
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
tr[p].max=-21000000;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
}
inline void change(int p,int l,int r,int x)//单点修改 l==r 故未加tag操作
{
if(l<=tr[p].l&&tr[p].r<=r)
{
if(tr[p].max!=-21000000)
tr[p].max+=x;
else
tr[p].max=x;
tr[p].s+=(tr[p].r-tr[p].l+1)*x;
}
else
{
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
change(p*2,l,r,x);
if(r>mid)
change(p*2+1,l,r,x);
up(p);
}
}
inline tree find(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p];
else
{
int mid=(tr[p].l+tr[p].r)/2;
bool flag1=false,flag2=false;
tree x1,x2;
if(l<=mid)
{
x1=find(p*2,l,r);
flag1=true;
}
if(r>mid)
{
x2=find(p*2+1,l,r);
flag2=true;
}
tree x;
x.max=-21000000;
if(flag1)
{
if(flag2)
{
x.max=max(x1.max,x2.max);
x.s=x1.s+x2.s;
}
else
x=x1;
}
else
x=x2;
return x;
}
}
int dep[100001],size[100001],son[100001],fa[100001];
int top[100001],w[100001];
int lson[100001]/*最大节点位置*/,mson[100001]/*最大节点值*/;
int tot;
inline void dfs1(int d)
{
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=fa[d])
{
dep[t]=dep[d]+1;
fa[t]=d;
dfs1(t);
son[d]+=son[t]+1;
if(son[t]>=mson[d])
{
mson[d]=son[t];
lson[d]=t;
}
}
}
}
inline void dfs2(int d)
{
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t==lson[d])
{
top[t]=top[d];
tot++;
w[t]=tot;
dfs2(t);
}
}
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=fa[d]&&t!=lson[d])
{
top[t]=t;
tot++;
w[t]=tot;
dfs2(t);
}
}
}
tree xx;
inline tree ask(int s,int t)
{
int u=top[s],v=top[t];
tree x,xt;
x=xx;
x.max=-21000000;
while(u!=v)
{
if(dep[u]>dep[v])
{
xt=find(1,w[u],w[s]);
x.max=max(x.max,xt.max);
x.s+=xt.s;
s=fa[top[s]];
}
else
{
xt=find(1,w[v],w[t]);
x.max=max(x.max,xt.max);
x.s+=xt.s;
t=fa[top[t]];
}
u=top[s];
v=top[t];
}
if(w[s]<w[t])
xt=find(1,w[s],w[t]);
else
xt=find(1,w[t],w[s]);
x.max=max(x.max,xt.max);
x.s+=xt.s;
return x;
}
int val[100001];
int main()
{
// freopen("count.in","r",stdin);
// freopen("count.out","w",stdout);
int n;
scanf("%d",&n);
int i,s,t;
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&s,&t);
edge++;
add(s,t);
edge++;
add(t,s);
}
dep[1]=1;
dfs1(1);
top[1]=1;
tot++;
w[1]=tot;
dfs2(1);
build(1,1,n);
for(i=1;i<=n;i++)
{
scanf("%d",&val[i]);
change(1,w[i],w[i],val[i]);
}
char x;
int m;
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%c",&x);
while(x=='\n'||x=='\r')
scanf("%c",&x);
if(x=='Q')
{
int flag=1;
scanf("%c",&x);
if(x=='M')
flag=1;
else
flag=2;
while(x!=' ')
scanf("%c",&x);
scanf("%d%d",&s,&t);
tree tx=ask(s,t);
if(flag==1)
printf("%d\n",tx.max);
else if(flag==2)
printf("%d\n",tx.s);
}
else if(x=='C')
{
while(x!=' ')
scanf("%c",&x);
scanf("%d%d",&s,&t);
change(1,w[s],w[s],-val[s]);
val[s]=t;
change(1,w[s],w[s],val[s]);
}
}
return 0;
}