题目描述
一棵树上有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本身
输入输出格式
输入格式:
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出格式:
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
输入输出样例
输入样例#1:
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:
4
1
2
2
10
6
5
6
5
16
说明
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
题解:我懒得写一棵线段树两种操作了,所以索性写了两棵线段树,一棵 清蒸 求区间最大值,一棵红烧 求区间和
单点修改的时候,就同时修改两棵树。查询就是最经典的路径查询啦~
代码写了4k,还暗自窃喜自己终于写了一长度4k的代码,回去一看,什么鬼,我树剖模板题都写的比这个长?
也是醉了,代码如下:
#include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define lson root<<1 #define rson root<<1|1 using namespace std; struct node { int m,l,r; } tr_sum[120120],tr_max[120120]; int size[30030],deep[30030],fa[30030],son[30030],id[30030],top[30030],w[30030],c[30030],cnt; vector<int> g[30030]; void push_up_sum(int root) { tr_sum[root].m=tr_sum[lson].m+tr_sum[rson].m; } void push_up_max(int root) { tr_max[root].m=max(tr_max[lson].m,tr_max[rson].m); } void build_sum(int root,int l,int r) { if(l==r) { tr_sum[root].l=l; tr_sum[root].r=r; tr_sum[root].m=w[l]; return ; } tr_sum[root].l=l; tr_sum[root].r=r; int mid=(l+r)>>1; build_sum(lson,l,mid); build_sum(rson,mid+1,r); push_up_sum(root); } void build_max(int root,int l,int r) { if(l==r) { tr_max[root].l=l; tr_max[root].r=r; tr_max[root].m=w[l]; return ; } tr_max[root].l=l; tr_max[root].r=r; int mid=(l+r)>>1; build_max(lson,l,mid); build_max(rson,mid+1,r); push_up_max(root); } void update(int root,int x,int val) { if(x==tr_sum[root].l&&x==tr_sum[root].r) { tr_sum[root].m=val; tr_max[root].m=val; return ; } int mid=(tr_sum[root].l+tr_sum[root].r)>>1; if(x>mid) { update(rson,x,val); } else { update(lson,x,val); } push_up_sum(root); push_up_max(root); } int query_sum(int root,int l,int r) { if(l==tr_sum[root].l&&r==tr_sum[root].r) { return tr_sum[root].m; } int mid=(tr_sum[root].l+tr_sum[root].r)>>1; if(l>mid) { return query_sum(rson,l,r); } else { if(r<=mid) { return query_sum(lson,l,r); } else { return query_sum(lson,l,mid)+query_sum(rson,mid+1,r); } } } int query_max(int root,int l,int r) { if(l==tr_max[root].l&&r==tr_max[root].r) { return tr_max[root].m; } int mid=(tr_max[root].l+tr_max[root].r)>>1; if(l>mid) { return query_max(rson,l,r); } else { if(r<=mid) { return query_max(lson,l,r); } else { return max(query_max(lson,l,mid),query_max(rson,mid+1,r)); } } } void dfs1(int now,int f,int dep) { fa[now]=f; deep[now]=dep; size[now]=1; int maxson=-1; for(int i=0; i<g[now].size(); i++) { if(g[now][i]==f) { continue; } dfs1(g[now][i],now,dep+1); size[now]+=size[g[now][i]]; if(size[g[now][i]]>maxson) { son[now]=g[now][i]; maxson=size[g[now][i]]; } } } void dfs2(int now,int topf) { id[now]=++cnt; w[cnt]=c[now]; top[now]=topf; if(!son[now]) { return ; } dfs2(son[now],topf); for(int i=0; i<g[now].size(); i++) { if(g[now][i]==fa[now]||g[now][i]==son[now]) { continue; } dfs2(g[now][i],g[now][i]); } } int path_query_max(int x,int y) { int ans=-100000; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) { swap(x,y); } ans=max(ans,query_max(1,id[top[x]],id[x])); x=fa[top[x]]; } if(deep[x]>deep[y]) { swap(x,y); } ans=max(ans,query_max(1,id[x],id[y])); return ans; } int path_query_sum(int x,int y) { int ans=0; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) { swap(x,y); } ans+=query_sum(1,id[top[x]],id[x]); x=fa[top[x]]; } if(deep[x]>deep[y]) { swap(x,y); } ans+=query_sum(1,id[x],id[y]); return ans; } int main() { int n,m; scanf("%d",&n); for(int i=1; i<=n-1; i++) { int from,to; scanf("%d%d",&from,&to); g[from].push_back(to); g[to].push_back(from); } for(int i=1; i<=n; i++) { scanf("%d",&c[i]); } dfs1(1,0,1); dfs2(1,1); build_sum(1,1,n); build_max(1,1,n); scanf("%d",&m); char s[10]; int u,v; for(int i=1; i<=m; i++) { scanf("\n%s %d %d",s,&u,&v); if(s[0]==‘C‘) { update(1,id[u],v); } if(s[0]==‘Q‘) { if(s[1]==‘S‘) { printf("%d\n",path_query_sum(u,v)); } if(s[1]==‘M‘) { printf("%d\n",path_query_max(u,v)); } } } }