HYSBZ 1036树链剖分
一棵树上有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本身
输入的第一行为一个整数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之间。
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input4
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
Hint
树链剖分+线段树模板题:
参考代码:
1 //树链剖分+线段树 2 /* 3 I. CHANGE u t : 把结点u的权值改为t 4 II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I 5 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 (包括u和v本身) 6 */ 7 #include<bits/stdc++.h> 8 using namespace std; 9 #define mem(a,b) memset(a,b,sizeof a) 10 #define mp make_pair 11 #define eps 1e-8 12 #define lson l,mid,rt<<1 13 #define rson mid+1,r,rt<<1|1 14 typedef long long ll; 15 typedef unsigned long long ull; 16 const int INF=0x3f3f3f3f; 17 const ll inf=0x3f3f3f3f3f3f3f3fll; 18 const int maxn=2e5+10; 19 int siz[maxn],top[maxn],fa[maxn],dep[maxn]; 20 int tid[maxn],rnk[maxn],son[maxn],cnt; 21 int head[maxn],tot,a[maxn]; 22 23 struct Node{ 24 int v,nxt; 25 } edge[maxn]; 26 27 struct Tree{ 28 int l,r,sz; 29 int sum,max_num; 30 } tree[maxn<<2]; 31 32 void Init() 33 { 34 tot=cnt=0; 35 mem(head,-1); mem(son,-1); 36 mem(siz,0); mem(top,0); 37 } 38 39 40 void Pushup(int pos) 41 { 42 tree[pos].max_num=max(tree[pos<<1].max_num,tree[pos<<1|1].max_num); 43 tree[pos].sum=tree[pos<<1].sum+tree[pos<<1|1].sum; 44 } 45 46 void Build(int l,int r,int rt) 47 { 48 tree[rt].l=l;tree[rt].r=r;tree[rt].sz=r-l+1; 49 if(l==r) 50 { 51 tree[rt].max_num=tree[rt].sum=a[rnk[l]]; 52 return ; 53 } 54 int mid=(l+r)>>1; 55 Build(lson); Build(rson); 56 Pushup(rt); 57 } 58 59 void Update(int pos,int c,int l,int r,int rt) 60 { 61 if(l==r) 62 { 63 tree[rt].max_num=tree[rt].sum=c; 64 return ; 65 } 66 int mid=(l+r)>>1; 67 if(pos<=mid) Update(pos,c,lson); 68 else Update(pos,c,rson); 69 Pushup(rt); 70 } 71 72 int Query_sum(int L,int R,int l,int r,int rt)//求L~R的和 73 { 74 if(l>=L && r<=R) return tree[rt].sum; 75 int mid=(l+r)>>1; 76 int ans=0; 77 if(L<=mid) ans+=Query_sum(L,R,lson); 78 if(R>mid) ans+=Query_sum(L,R,rson); 79 return ans; 80 } 81 82 int Query_max(int L,int R,int l,int r,int rt)//寻找L~R的最大值 83 { 84 if(L<=l && r<=R) return tree[rt].max_num; 85 int mid=(l+r)>>1; 86 int ans=-INF; 87 if(L<=mid) ans=max(ans,Query_max(L,R,lson)); 88 if(R>mid) ans=max(ans,Query_max(L,R,rson)); 89 return ans; 90 } 91 92 void addedge(int u,int v) 93 { 94 edge[tot].v=v; 95 edge[tot].nxt=head[u]; 96 head[u]=tot++; 97 } 98 99 void dfs1(int u,int father,int depth) 100 { 101 fa[u]=father; 102 dep[u]=depth; 103 siz[u]=1; 104 for(int i=head[u];~i;i=edge[i].nxt) 105 { 106 int v=edge[i].v; 107 if(v!=fa[u]) 108 { 109 dfs1(v,u,depth+1); 110 siz[u]+=siz[v]; 111 if(son[u]==-1 || siz[v]>siz[son[u]]) son[u]=v; 112 } 113 } 114 } 115 116 void dfs2(int u,int t) 117 { 118 top[u]=t; 119 tid[u]=++cnt; rnk[cnt]=u;//tid[]:表示该点在线段树中的位置/:rnk[]:和tid[]数组相反,根据线段树中的位置,找到树中位置 120 if(son[u]==-1) return ; 121 dfs2(son[u],t); 122 for(int i=head[u];~i;i=edge[i].nxt) 123 { 124 int v=edge[i].v; 125 if(v!=son[u] && v!=fa[u]) dfs2(v,v); 126 } 127 } 128 129 int LCA(int u,int v,int flag)//沿着树链求LCA(根据flag的不同,求不同的值) 130 { 131 int fu=top[u],fv=top[v],res; 132 if(flag) res=-INF;// flag=1 求最大值 133 else res=0; //flag=0 求和 134 while(fu!=fv) 135 { 136 if(dep[fu]<dep[fv]) swap(fu,fv),swap(u,v); 137 if(flag) res=max(res,Query_max(tid[fu],tid[u],1,cnt,1)); 138 else res+=Query_sum(tid[fu],tid[u],1,cnt,1); 139 u=fa[fu],fu=top[u]; 140 } 141 if(dep[u]>dep[v]) swap(u,v); 142 if(flag) res=max(res,Query_max(tid[u],tid[v],1,cnt,1)); 143 else res+=Query_sum(tid[u],tid[v],1,cnt,1); 144 return res; 145 } 146 147 int main() 148 { 149 int n,t,u,v,w; 150 char op[10]; 151 while(~scanf("%d",&n)) 152 { 153 Init(); 154 for(int i=1;i<n;i++) 155 { 156 scanf("%d%d",&u,&v); 157 addedge(u,v); 158 addedge(v,u); 159 } 160 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 161 dfs1(1,0,0); 162 dfs2(1,1); 163 Build(1,cnt,1); 164 scanf("%d",&t); 165 while(t--) 166 { 167 scanf("%s",op); 168 scanf("%d%d",&u,&v); 169 if(op[1]=='S') printf("%d\n",LCA(u,v,0)); 170 else if(op[1]=='M') printf("%d\n",LCA(u,v,1)); 171 else Update(tid[u],v,1,cnt,1); 172 } 173 } 174 return 0; 175 } 176