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本身

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

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
",LCA(u,v,0));
170             else if(op[1]=='M') printf("%d
",LCA(u,v,1));
171             else Update(tid[u],v,1,cnt,1);
172         }
173     }
174     return 0;
175 }
176   
View Code
原文地址:https://www.cnblogs.com/csushl/p/9704379.html