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
这是一道较水的码农题,我的作法是树链剖分套zkw线段树,我们沿着重链的路径建立线段树,最多有
log(n)
条重链,线段树对每条链询问,所以一次询问是
O(log(n)2)
的,所以总的复杂度是
O(q∗log(n)2)
可以轻松过掉。
注意点:答案有负数,max询问初始的res不能是0
码农题挂了多多debug,断点输出,自己随机小数据,就能找到原因了
树上的就考虑链,菊花等数据debug一下,比如刚开始我的代码漏洞也很多,于是满满的debug
代码:
/**************************************************************
Problem: 1036
User: waz
Language: C++
Result: Accepted
Time:1900 ms
Memory:4032 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define cut_print puts("All of is all right")
//树链剖分套zkw线段树
namespace work_space{
const int maxn=30010;
int v[maxn];
int siz[maxn],fa[maxn],dep[maxn],son[maxn];
int dfn[maxn],top[maxn],timer;
//树链剖分
struct edge{int to;edge*next;}*last[maxn],e[maxn<<1],*et=e;
void add(int u,int v){
*++et=(edge){v,last[u]},last[u]=et;
*++et=(edge){u,last[v]},last[v]=et;
}
void dfs1(int u){
dep[u]=dep[fa[u]]+1;
siz[u]=1;
for(edge*it=last[u];it;it=it->next)
if(fa[u]!=it->to){
fa[it->to]=u;
dfs1(it->to);
siz[u]+=siz[it->to];
if(siz[it->to]>siz[son[u]])
son[u]=it->to;
}
}
void dfs2(int u,int tp){
top[u]=tp;
dfn[u]=++timer;
if(son[u])dfs2(son[u],tp);
for(edge*it=last[u];it;it=it->next)
if(fa[it->to]==u&&son[u]!=it->to)
dfs2(it->to,it->to);
}
//根据dfs序建立zkw线段树
int seg_max[maxn<<2],seg_sum[maxn<<2],cnt;
void update(int pos){
seg_max[pos]=std::max(seg_max[pos<<1],seg_max[pos<<1|1]);
seg_sum[pos]=seg_sum[pos<<1]+seg_sum[pos<<1|1];
}
void init(int n){
for(cnt=1;cnt<=n+1;cnt<<=1);cnt--;
for(int i=1;i<=n;i++)seg_max[dfn[i]+cnt]=seg_sum[dfn[i]+cnt]=v[i];
for(int i=cnt;i;i--)update(i);
}
void modity(int pos,int x){
//printf("pos = %d x = %d\n",pos,x);
v[pos]=x;pos=dfn[pos]+cnt;
seg_max[pos]=seg_sum[pos]=x;
for(pos>>=1;pos;pos>>=1)update(pos);
}
int query_sum(int s,int t){
s=dfn[s],t=dfn[t];
if(s>t)std::swap(s,t);
int res=0;
for(s+=cnt-1,t+=cnt+1;s^t^1;s>>=1,t>>=1)
s&1?:res+=seg_sum[s^1],t&1?res+=seg_sum[t^1]:1;
return res;
}
int query_max(int s,int t){
s=dfn[s],t=dfn[t];
if(s>t)std::swap(s,t);
int res=-1<<30;
for(s+=cnt-1,t+=cnt+1;s^t^1;s>>=1,t>>=1)
s&1?:res=std::max(seg_max[s^1],res),t&1?res=std::max(res,seg_max[t^1]):1;
return res;
}
int qmax(int u,int v){
int ans=-1<<30;
for(;top[u]!=top[v];){
if(dep[top[u]]>dep[top[v]]){
ans=std::max(ans,query_max(u,top[u]));
u=fa[top[u]];
} else {
ans=std::max(ans,query_max(v,top[v]));
v=fa[top[v]];
}
}
ans=std::max(ans,query_max(u,v));
return ans;
}
int qsum(int u,int v){
int ans=0;
for(;top[u]!=top[v];){
//printf("(u, v) = (%d, %d)\n",u,v);
if(dep[top[u]]>dep[top[v]]){
ans+=query_sum(u,top[u]);
u=fa[top[u]];
} else {
ans+=query_sum(v,top[v]);
v=fa[top[v]];
}
}
ans+=query_sum(u,v);
return ans;
}
int n,q;
char op[10];
void main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);//
}
for(int i=1;i<=n;i++)scanf("%d",v+i);
dfs1(1),dfs2(1,1),init(n);
//for(int i=1;i<=n;i++)printf("i = %d , fa = %d , top = %d\n",i,fa[i],top[i]);
scanf("%d",&q);
for(;q--;){
scanf("%s",op);
int o;
if(!strcmp(op,"QMAX"))o=1;
else if(!strcmp(op,"QSUM"))o=2;
else o=3;
if(o==1){
int u,v;
scanf("%d%d",&u,&v);
//printf("top[%d] = %d , top[%d] = %d\n",u,top[u],v,top[v]);
printf("%d\n",qmax(u,v));
//OK!
} else if(o==2) {
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",qsum(u,v));
} else {
int pos,x;
scanf("%d%d",&pos,&x);//cut_print;
modity(pos,x);
}
}
}
}
#define set_file(x) freopen(#x".in","r",stdin),freopen("my_"#x".out","w",stdout)
int main(){
//set_file(count1);
work_space::main();
return 0;
}