题目描述
一棵树上有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: 复制
View Code
4 1 2 2 10 6 5 6 5 16
树剖模板题
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 typedef pair<int,int>pii; ////////////////////////////////// const int N=2e6+10; const int M=1e6; int t[N<<2],col[N<<2],w[N],n,mod,m,root,node[N],t2[N<<2]; void up(int pos) { t[pos]=t[pos<<1]+t[pos<<1|1]; t2[pos]=max(t2[pos<<1],t2[pos<<1|1]); } void build(int l,int r,int pos) { col[pos]=0; if(l==r){t[pos]=t2[pos]=w[l];return ;}//w为重新编号的权值 int m=(l+r)>>1; build(lson);build(rson); up(pos); } void update(int L,int R,int x,int l,int r,int pos) { if(L<=l&&r<=R) { t[pos]=x;t2[pos]=x;return ; } //down(r-l+1,pos); int m=(l+r)>>1; if(L<=m)update(L,R,x,lson); if(R>m)update(L,R,x,rson); up(pos); } int query(int L,int R,int l,int r,int pos) { int ans=0; if(L<=l&&r<=R)return t[pos]; //down(r-l+1,pos); int m=(l+r)>>1; if(L<=m)ans+=query(L,R,lson); if(R>m)ans+=query(L,R,rson); up(pos); return ans; } int querymax(int L,int R,int l,int r ,int pos) { int ans=-inf; if(L<=l&&r<=R)return t2[pos]; int m=(l+r)>>1; if(L<=m)ans=max(ans,querymax(L,R,lson)); if(R>m)ans=max(ans,querymax(L,R,rson)); return ans; } /////////////////////////////// int dep[N],siz[N],fa[N],son[N],head[M],pos,id[N],top[N],cnt; struct Edge { int to,nex; }edge[M]; void add(int a,int b) { edge[++pos].nex=head[a]; edge[pos].to=b; head[a]=pos; } void dfs1(int x,int f,int deep) { dep[x]=deep; fa[x]=f; siz[x]=1; int maxson=-1; for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(v==f)continue; dfs1(v,x,deep+1); siz[x]+=siz[v]; if(siz[v]>maxson)maxson=siz[v],son[x]=v; } } void dfs2(int x,int topf) { id[x]=++cnt; w[cnt]=node[x]; top[x]=topf; if(!son[x])return; dfs2(son[x],topf); for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(v==fa[x]||v==son[x])continue; dfs2(v,v); } } int qrange(int x,int y)//询问x到y最短路径的权值和 { int ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); ans+=query(id[top[x]],id[x],1,n,1); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans=(ans+query(id[x],id[y],1,n,1)); return ans; } int qmax(int x,int y) { int ans=-inf; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); ans=max(ans,querymax(id[top[x]],id[x],1,n,1) ); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans=max(ans,querymax(id[x],id[y],1,n,1)); return ans; } int main() { RI(n); rep(i,1,n-1){int a,b;RII(a,b);add(a,b);add(b,a);} rep(i,1,n)RI(node[i]); dfs1(1,0,1);dfs2(1,1); build(1,n,1); RI(m); rep(i,1,m) { string s;cin>>s;int a,b; if(s=="QMAX"){RII(a,b);printf("%d ",qmax(a,b));} else if(s=="QSUM"){RII(a,b);printf("%d ",qrange(a,b));} else RII(a,b),update(id[a],id[a],b,1,n,1); } return 0; }