【ZJOI2008】 树的统计 count

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

Sample Output

4
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\n",_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\n",_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 }
BZOJ 1036

 

你可能感兴趣的:(count)