Description
一 棵树上有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本身
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
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
1
2
2
10
6
5
6
5
16
思路
又是从浙江挂下来的考数据结构的歪风邪气。
树链剖分。不过我们不以边为元素,而以点为元素。由于一个点有可能被访问两次,所以在判重方面有一些麻烦。
大体的思想是每次把点向上提的时候处理提到的节点,但不处理当前的节点。。
恩。。这份代码应该是写的比较差吧,就当复习树链剖分了。
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #include <queue> 9 #include <stack> 10 #include <map> 11 #include <set> 12 #include <list> 13 #include <vector> 14 #include <ctime> 15 #include <functional> 16 #define pritnf printf 17 #define scafn scanf 18 #define sacnf scanf 19 #define For(i,j,k) for(int i=(j);i<=(k);(i)++) 20 #define Clear(a) memset(a,0,sizeof(a)) 21 using namespace std; 22 typedef unsigned int Uint; 23 const int INF=0x3fffffff; 24 ///==============struct declaration============== 25 26 ///==============var declaration================= 27 const int MAXN=30050; 28 int n,q,tot=0,k,v,L,R; 29 int siz[MAXN],son[MAXN],fa[MAXN],top[MAXN],val[MAXN],No[MAXN],depth[MAXN]; 30 int sum[MAXN*5],maxv[MAXN*5]; 31 vector <int> Edge[MAXN]; 32 ///==============function declaration============ 33 void dfs1(int x);void dfs2(int x);void Init(); 34 void Set_Seg(int o,int l,int r); 35 void update(int o,int l,int r); 36 int Query_Max(int o,int l,int r); 37 int Query_Sum(int o,int l,int r); 38 ///==============main code======================= 39 int main() 40 { 41 #define FILE__ 42 #ifdef FILE__ 43 freopen("input","r",stdin); 44 freopen("output","w",stdout); 45 #endif 46 scanf("%d",&n); 47 for(int i=1;i<n;i++){ 48 int s,e;scanf("%d%d",&s,&e); 49 Edge[s].push_back(e);Edge[e].push_back(s); 50 } 51 for(int i=1;i<=n;i++) scanf("%d",val+i); 52 depth[1]=1;top[1]=1;dfs1(1);dfs2(1); 53 for(int i=1;i<=n;i++){ 54 v=val[i],k=No[i]; 55 Set_Seg(1,1,n); 56 } 57 scanf("%d",&q); 58 while (q--){ 59 char cmd[10];scanf("%s",cmd); 60 if (cmd[1]=='M'){///QMAX 61 int _max=-INF;int u,v; 62 scanf("%d%d",&u,&v);if (u==v) _max=val[u]; 63 _max=max(_max,val[u]); 64 _max=max(_max,val[v]);///if the point locates at a top of a Heavy String 65 while (u!=v){ 66 if (depth[top[u]]<depth[top[v]]) swap(u,v);///Make u is always deeper 67 if (top[u]==top[v]){///Locate at the same Heavy String 68 L=No[u],R=No[v];if (L>R) swap(L,R);L++;R--; 69 if (L<=R) 70 _max=max(_max,Query_Max(1,1,n)); 71 break; 72 } 73 if (top[u]==u){///Top of a heavy string 74 u=fa[u]; 75 _max=max(_max,val[u]); 76 } 77 else{///middle of a heavy string 78 L=No[top[u]],R=No[u];if (L>R) swap(L,R);R--; 79 _max=max(_max,Query_Max(1,1,n));u=top[u]; 80 } 81 } 82 printf("%d ",_max); 83 } 84 else if (cmd[1]=='S'){///QSUM 85 int _sum=0;int u,v; 86 scanf("%d%d",&u,&v); 87 _sum+=val[u]; 88 if (u!=v) _sum+=val[v];///if the point locates at a top of a Heavy String 89 while (u!=v){ 90 if (depth[top[u]]<depth[top[v]]) swap(u,v);///Make u is always deeper 91 if (top[u]==top[v]){///Locate at the same Heavy String 92 L=No[v],R=No[u];if (L>R) swap(L,R);L++;R--; 93 if (L<=R) 94 _sum+=Query_Sum(1,1,n); 95 break; 96 } 97 if (top[u]==u){///Top of a heavy string 98 u=fa[u]; 99 if (u!=v) 100 _sum+=val[u]; 101 } 102 else{///middle of a heavy string 103 L=No[top[u]],R=No[u];if (L>R) swap(L,R);R--; 104 _sum+=Query_Sum(1,1,n);u=top[u]; 105 } 106 } 107 printf("%d ",_sum); 108 } 109 else if (cmd[1]=='H'){///Change 110 scanf("%d%d",&k,&v);val[k]=v;k=No[k]; 111 Set_Seg(1,1,n); 112 } 113 } 114 return 0; 115 } 116 ///================fuction code==================== 117 void dfs1(int x){ 118 siz[x]=1;son[x]=-1; 119 for(int i=0;i<Edge[x].size();i++){ 120 int &e=Edge[x][i]; 121 if (fa[x]==e) continue; 122 fa[e]=x;depth[e]=depth[x]+1;dfs1(e); 123 siz[x]+=siz[e]; 124 if (son[x]==-1||siz[son[x]]<siz[e]) 125 son[x]=e; 126 } 127 } 128 void dfs2(int x){ 129 No[x]=++tot; 130 if (siz[x]!=1) { 131 top[son[x]]=top[x]; 132 dfs2(son[x]); 133 } 134 for(int i=0;i<Edge[x].size();i++){ 135 int &e=Edge[x][i]; 136 if (son[x]==e||fa[x]==e) continue; 137 top[e]=e;dfs2(e); 138 } 139 } 140 void Set_Seg(int o,int l,int r){ 141 int m=(l+r)>>1,lc=o*2,rc=o*2+1; 142 if (l==r){ 143 sum[o]=maxv[o]=v; 144 return; 145 } 146 if (m>=k) Set_Seg(lc,l,m); 147 else Set_Seg(rc,m+1,r); 148 update(o,l,r); 149 } 150 void update(int o,int l,int r){ 151 int lc=o*2,rc=o*2+1; 152 sum[o]=sum[lc]+sum[rc]; 153 maxv[o]=max(maxv[lc],maxv[rc]); 154 } 155 int Query_Max(int o,int l,int r){ 156 if (L<=l&&r<=R) 157 return maxv[o]; 158 int m=(l+r)>>1,lc=o*2,rc=o*2+1; 159 int Left=-INF,Right=-INF; 160 if (m>=L) Left=Query_Max(lc,l,m); 161 if (m<R) Right=Query_Max(rc,m+1,r); 162 return max(Left,Right); 163 } 164 int Query_Sum(int o,int l,int r){ 165 if (L<=l&&r<=R) 166 return sum[o]; 167 int m=(l+r)>>1,lc=o*2,rc=o*2+1; 168 int Left=0,Right=0; 169 if (m>=L) Left=Query_Sum(lc,l,m); 170 if (m<R) Right=Query_Sum(rc,m+1,r); 171 return Left+Right; 172 }