[ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 15802 Solved: 6447
[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
Sample Output
4
1
2
2
10
6
5
6
5
16
手速题,我一个老年选手就调了30min……
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 30005;
int rk[MAXN],loc[MAXN],cnt;
int sum[MAXN<<2],big[MAXN<<2];
int data[MAXN];
int h[MAXN],to[MAXN<<1],nx[MAXN<<1],len;
int dep[MAXN],ch[MAXN],top[MAXN],sz[MAXN],fa[MAXN];
int n,m;
char in[80];
const char sa[]={"QSUM"},sb[]={"QMAX"},sc[]={"CHANGE"};
struct ans{
int summ,bigm;
};
void ins(int u,int v){
len++;to[len]=v;nx[len]=h[u];h[u]=len;
len++;to[len]=u;nx[len]=h[v];h[v]=len;
}
void pushup(int nd){
sum[nd]=sum[nd<<1]+sum[nd<<1|1];
big[nd]=max(big[nd<<1],big[nd<<1|1]);
}
void build(int rt,int l,int r){
if(l==r){
sum[rt]=big[rt]=data[loc[l]];
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
int lca(int a,int b){
while(top[a]!=top[b]){
dep[top[a]] > dep[top[b]] ? a=fa[top[a]] : b=fa[top[b]];
}
return dep[a]<dep[b]?a:b;
}
ans query(int rt,int L,int R,int l,int r){
//if(l>r)swap(l,r);
// cout<<rt<<" "<<L<<" "<<R<<" "<<l<<" "<<r<<endl;
ans ret=(ans){0,-0x7ffffff};
if(l<=L && r>=R)
{
ret=(ans){sum[rt],big[rt]};
return ret;
}
int mid=(L+R)>>1;
if(l>mid)
{
return query(rt<<1|1,mid+1,R,l,r);
}
else if(r<=mid)
{
return query(rt<<1,L,mid,l,r);
}
else
{
ans _a,_b;
_a=query(rt<<1,L,mid,l,mid);
_b=query(rt<<1|1,mid+1,R,mid+1,r);
// cout<<_a.summ<<" "<<_b.summ<<endl;
ret=(ans){_a.summ+_b.summ,max(_a.bigm,_b.bigm)};
}
return ret;
}
void modify(int rt,int l,int r,int loc,int d)
{
if(l>r)swap(l,r);
if(l==r)
{
sum[rt]=big[rt]=d;return;
}
int mid=(l+r)>>1;
if(loc>mid)
{
modify(rt<<1|1,mid+1,r,loc,d);
}
else
{
modify(rt<<1,l,mid,loc,d);
}
pushup(rt);
}
void change(int loc,int t)
{
modify(1,1,cnt,rk[loc],t);
}
/*
ans getans(int u,int v)
{
int l=lca(u,v);
ans ret=(ans){0,0},buf;
while(top[u]!=top[l])
{
buf=query(1,1,cnt,rk[u],top[u]);
u=fa[top[u]];
ret.summ+=buf.summ;
ret.bigm=max(ret.bigm,buf.bigm);
}
buf=query(1,1,cnt,rk[u],rk[l]);
ret.summ+=buf.summ;
ret.bigm=max(ret.bigm,buf.bigm);
while(top[v]!=top[l])
{
buf=query(1,1,cnt,rk[v],top[v]);
v=fa[top[v]];
ret.summ+=buf.summ;
ret.bigm=max(ret.bigm,buf.bigm);
}
buf=query(1,1,cnt,rk[v],rk[l]);
ret.summ+=buf.summ;
ret.bigm=max(ret.bigm,buf.bigm);
return ret;
}
*/
ans getans(int u,int v)
{
ans ret=(ans){0,-0x7ffffff};
while(top[u] != top[v])
{
// cout<<u<<" "<<v<<" "<<dep[u]<<" "<<dep[v]<<" "<<rk[top[u]]<<" "<<rk[u]<<endl;
if(dep[top[u]] > dep[top[v]])
{
ans _b=query(1,1,cnt,rk[top[u]],rk[u]);
ret.summ+=_b.summ;
ret.bigm=max(ret.bigm,_b.bigm);
u=fa[top[u]];
}
else
{
ans _b=query(1,1,cnt,rk[top[v]],rk[v]);
ret.summ+=_b.summ;
ret.bigm=max(ret.bigm,_b.bigm);
v=fa[top[v]];
// cout<<"finished\n";
}
}
if(dep[u]>dep[v])
{
swap(u,v);
}
//cout<<rk[u]<<" "<<rk[v]<<endl;
ans _b=query(1,1,cnt,rk[u],rk[v]);
//cout<<query(1,1,cnt,rk[1],rk[3]).summ<<endl;
// cout<<_b.summ<<endl;
ret.summ+=_b.summ;
ret.bigm=max(ret.bigm , _b.bigm);
// cout<<ret.summ<<endl;
return ret;
}
void dfs1(int nd,int pr){
fa[nd]=pr;
dep[nd]=dep[pr]+1;
sz[nd]=1;
for(int i=h[nd];i;i=nx[i]){
if(to[i] != fa[nd]){
dfs1(to[i],nd);
sz[nd]+=sz[to[i]];
if(sz[to[i]] > sz[ch[nd]])
ch[nd]=to[i];
}
}
}
void dfs2(int nd,int tp){
top[nd]=tp;
rk[nd]=++cnt;
loc[cnt]=nd;
if(ch[nd]!=0)dfs2(ch[nd],tp);
for(int i=h[nd];i;i=nx[i]){
if(to[i]!=fa[nd] && to[i]!=ch[nd]){
dfs2(to[i],to[i]);
}
}
}
int check()
{
if(!strcmp(in,sa))return 1;
if(!strcmp(in,sb))return 2;
if(!strcmp(in,sc))return 3;
return 233;
}
int main(){
// freopen("bzoj_1036.in","r",stdin);
// freopen("bzoj_1036.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n-1;i++){
int a,b;
scanf("%d%d",&a,&b);
ins(a,b);
}
for(int i=1;i<=n;i++)
scanf("%d",&data[i]);
dfs1(1,0);
dfs2(1,1);
//cout<<lca(4,3)<<endl;
build(1,1,cnt);
// cout<<query(1,1,n,rk[1],rk[top[1]]).bigm<<endl;
scanf("%d",&m);
/*
for(int i=1;i<=n;i++)
cout<<rk[i]<<" ";
*/
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%s %d %d",in,&a,&b);
int f=check();
ans rt;
switch(f)
{
case 1:
rt=getans(a,b);
printf("%d\n",rt.summ);
break;
case 2:
rt=getans(a,b);
printf("%d\n",rt.bigm);
break;
case 3:
change(a,b);
break;
default:
puts("233");
}
}
return 0;
}