洛谷——P2590 [ZJOI2008]树的统计
https://www.luogu.org/problem/show?pid=2590#sub
题目描述
一棵树上有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之间。
树剖模板
1 #include <algorithm> 2 #include <string> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N(30000+15); 8 int n,u,v,val[N],q; 9 char op[10]; 10 11 int head[N],sumedge; 12 struct Edge 13 { 14 int u,v,next; 15 Edge(int u=0,int v=0,int next=0): 16 u(u),v(v),next(next){} 17 }edge[N<<1]; 18 void ins(int u,int v) 19 { 20 edge[++sumedge]=Edge(u,v,head[u]); 21 head[u]=sumedge; 22 } 23 24 int cnt,id[N],dfn[N],size[N],son[N],top[N],dad[N],deep[N]; 25 void DFS(int u,int father,int deepth) 26 { 27 deep[u]=deepth; 28 dad[u]=father; 29 size[u]=1; 30 son[u]=0; 31 for(int i=head[u];i;i=edge[i].next) 32 { 33 int to=edge[i].v; 34 if(dad[u]==to) continue; 35 DFS(to,u,deepth+1); size[u]+=size[to]; 36 if(!son[u]||size[son[u]]<size[to]) son[u]=to; 37 } 38 } 39 void DFS_(int u,int Top) 40 { 41 top[u]=Top; 42 id[u]=++cnt; 43 dfn[cnt]=u; 44 if(son[u]) DFS_(son[u],Top); 45 for(int i=head[u];i;i=edge[i].next) 46 { 47 int to=edge[i].v; 48 if(to!=dad[u]&&to!=son[u]) DFS_(to,to); 49 } 50 } 51 52 struct Tree 53 { 54 int l,r,mid,sumval,maxval; 55 }tree[N<<2]; 56 void Tree_up(int now) 57 { 58 tree[now].sumval=tree[now<<1].sumval+tree[now<<1|1].sumval; 59 tree[now].maxval=max(tree[now<<1].maxval,tree[now<<1|1].maxval); 60 } 61 void Tree_build(int now,int l,int r) 62 { 63 tree[now].l=l;tree[now].r=r; 64 if(l==r) 65 { 66 tree[now].maxval=val[dfn[l]]; 67 tree[now].sumval=val[dfn[l]]; 68 return ; 69 } 70 tree[now].mid=l+r>>1; 71 Tree_build(now<<1,l,tree[now].mid); 72 Tree_build(now<<1|1,tree[now].mid+1,r); 73 Tree_up(now); 74 } 75 void Tree_change(int now,int to,int x) 76 { 77 if(tree[now].l==tree[now].r) 78 { 79 tree[now].maxval=x; 80 tree[now].sumval=x; 81 return ; 82 } 83 if(tree[now].mid>=to) Tree_change(now<<1,to,x); 84 else if(tree[now].mid<to) Tree_change(now<<1|1,to,x); 85 Tree_up(now); 86 } 87 int Tree_querymax(int now,int l,int r) 88 { 89 if(tree[now].l==l&&tree[now].r==r) return tree[now].maxval; 90 if(tree[now].mid>=r) return Tree_querymax(now<<1,l,r); 91 else if(tree[now].mid<l) return Tree_querymax(now<<1|1,l,r); 92 else return max(Tree_querymax(now<<1,l,tree[now].mid),Tree_querymax(now<<1|1,tree[now].mid+1,r)); 93 } 94 int Tree_querysum(int now,int l,int r) 95 { 96 if(tree[now].l==l&&tree[now].r==r) return tree[now].sumval; 97 if(tree[now].mid>=r) return Tree_querysum(now<<1,l,r); 98 else if(tree[now].mid<l) return Tree_querysum(now<<1|1,l,r); 99 else return Tree_querysum(now<<1,l,tree[now].mid)+Tree_querysum(now<<1|1,tree[now].mid+1,r); 100 } 101 102 int List_querymax(int x,int y) 103 { 104 int ret=-1e9; 105 for(;top[x]!=top[y];x=dad[top[x]]) 106 { 107 if(deep[top[x]]<deep[top[y]]) swap(x,y); 108 ret=max(ret,Tree_querymax(1,id[top[x]],id[x])); 109 } 110 if(id[x]>id[y]) swap(x,y); 111 ret=max(ret,Tree_querymax(1,id[x],id[y])); 112 return ret; 113 } 114 int List_querysum(int x,int y) 115 { 116 int ret=0; 117 for(;top[x]!=top[y];x=dad[top[x]]) 118 { 119 if(deep[top[x]]<deep[top[y]]) swap(x,y); 120 ret+=Tree_querysum(1,id[top[x]],id[x]); 121 } 122 if(id[x]>id[y]) swap(x,y); 123 ret+=Tree_querysum(1,id[x],id[y]); 124 return ret; 125 } 126 127 int main() 128 { 129 scanf("%d",&n); 130 for(int i=1;i<n;i++) 131 scanf("%d%d",&u,&v),ins(u,v),ins(v,u); 132 for(int i=1;i<=n;i++) scanf("%d",val+i); 133 DFS(1,0,1);DFS_(1,1); 134 Tree_build(1,1,n); 135 scanf("%d",&q); 136 for(;q--;) 137 { 138 scanf("%s%d%d",op,&u,&v); 139 if(op[0]=='C') Tree_change(1,id[u],v); 140 else if(op[1]=='M') printf("%d\n",List_querymax(u,v)); 141 else printf("%d\n",List_querysum(u,v)); 142 } 143 return 0; 144 }
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。