BZOJ 1036: [ZJOI2008]树的统计Count

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 3427   Solved: 1429
[ Submit][ Status]

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”的操作,每行输出一个整数表示要求输出的结果。

 
分析:
  裸的树链剖分。注意一下,输入的节点权值的下标要改为在线段树上的节点下标。
 
  1 #include <set>

  2 #include <map>

  3 #include <list>

  4 #include <cmath>

  5 #include <queue>

  6 #include <stack>

  7 #include <string>

  8 #include <vector>

  9 #include <cstdio>

 10 #include <cstring>

 11 #include <iostream>

 12 #include <algorithm>

 13 

 14 using namespace std;

 15 

 16 typedef long long ll;

 17 typedef unsigned long long ull;

 18 

 19 #define debug puts("here")

 20 #define rep(i,n) for(int i=0;i<n;i++)

 21 #define rep1(i,n) for(int i=1;i<=n;i++)

 22 #define REP(i,a,b) for(int i=a;i<=b;i++)

 23 #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

 24 #define pb push_back

 25 #define RD(n) scanf("%d",&n)

 26 #define RD2(x,y) scanf("%d%d",&x,&y)

 27 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

 28 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

 29 #define All(vec) vec.begin(),vec.end()

 30 #define MP make_pair

 31 #define PII pair<int,int>

 32 #define PQ priority_queue

 33 #define cmax(x,y) x = max(x,y)

 34 #define cmin(x,y) x = min(x,y)

 35 #define Clear(x) memset(x,0,sizeof(x))

 36 /*

 37 

 38 #pragma comment(linker, "/STACK:1024000000,1024000000")

 39 

 40 int size = 256 << 20; // 256MB

 41 char *p = (char*)malloc(size) + size;

 42 __asm__("movl %0, %%esp\n" :: "r"(p) );

 43 

 44 */

 45 

 46 /******** program ********************/

 47 

 48 const int MAXN = 100005;

 49 const int INF = 1e9;

 50 

 51 int val[MAXN];

 52 int po[MAXN],tol;

 53 int sz[MAXN],dep[MAXN],fa[MAXN],son[MAXN],tid[MAXN],top[MAXN];

 54 bool use[MAXN];

 55 int tot;

 56 int mx,msum;

 57 

 58 struct node{

 59     int y,next;

 60 }edge[MAXN];

 61 

 62 struct Tree{

 63     int l,r,mx,sum;

 64     inline int mid(){

 65         return (l+r)>>1;

 66     }

 67 }tree[MAXN<<2];

 68 

 69 inline void add(int x,int y){

 70     edge[++tol].y = y;

 71     edge[tol].next = po[x];

 72     po[x] = tol;

 73 }

 74 

 75 void dfsFind(int x,int pa,int depth){

 76     use[x] = true;

 77     dep[x] = depth;

 78     fa[x] = pa;

 79     sz[x] = 1;

 80     son[x] = 0;

 81 

 82     for(int i=po[x];i;i=edge[i].next){

 83         int y = edge[i].y;

 84         if(use[y])continue;

 85         dfsFind(y,x,depth+1);

 86         sz[x] += sz[y];

 87         if(sz[y]>sz[ son[x] ])

 88             son[x] = y;

 89     }

 90 }

 91 

 92 void dfsCon(int x,int pa){

 93     use[x] = true;

 94     tid[x] = ++ tot;

 95     top[x] = pa;

 96     if(son[x])

 97         dfsCon(son[x],pa);

 98     for(int i=po[x];i;i=edge[i].next){

 99         int y = edge[i].y;

100         if(use[y])continue;

101         dfsCon(y,y);

102     }

103 }

104 

105 inline void update(int rt){

106     tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum;

107     tree[rt].mx = max( tree[rt<<1].mx , tree[rt<<1|1].mx );

108 }

109 

110 void build(int l,int r,int rt){

111     tree[rt].l = l;

112     tree[rt].r = r;

113     if(l==r){

114         tree[rt].sum = tree[rt].mx = val[l];

115         return;

116     }

117     int mid = tree[rt].mid();

118     build(l,mid,rt<<1);

119     build(mid+1,r,rt<<1|1);

120 

121     update(rt);

122 }

123 

124 void modify(int pos,int c,int rt){

125     if(tree[rt].l==tree[rt].r){

126         tree[rt].sum = tree[rt].mx = c;

127         return;

128     }

129     int mid = tree[rt].mid();

130     if(pos<=mid)

131         modify(pos,c,rt<<1);

132     else

133         modify(pos,c,rt<<1|1);

134 

135     update(rt);

136 }

137 

138 void ask(int l,int r,int rt){

139     if(tree[rt].l==l&&tree[rt].r==r){

140         mx = max(mx,tree[rt].mx);

141         //cmax( mx , tree[rt].mx );

142         msum += tree[rt].sum;

143         return;

144     }

145     int mid = tree[rt].mid();

146     if(r<=mid)

147         ask(l,r,rt<<1);

148     else if(l>mid)

149         ask(l,r,rt<<1|1);

150     else{

151         ask(l,mid,rt<<1);

152         ask(mid+1,r,rt<<1|1);

153     }

154 }

155 

156 int main(){

157 

158 #ifndef ONLINE_JUDGE

159     freopen("sum.in","r",stdin);

160     //freopen("sum.out","w",stdout);

161 #endif

162 

163     int n,m,x,y;

164     while(cin>>n){

165         Clear(po);

166         tol = 1;

167 

168         REP(i,2,n){

169             RD2(x,y);

170             add(x,y);

171             add(y,x);

172         }

173 

174         Clear(use);

175         dfsFind(1,1,1);

176 

177         Clear(use);

178         tot = 0;

179         dfsCon(1,1);

180 

181         rep1(i,n){

182             RD(y);

183             val[ tid[i] ] = y;

184         }

185 

186         build(1,n,1);

187 

188         RD(m);

189         char op[10];

190         while(m--){

191             scanf("%s%d%d",op,&x,&y);

192             if(op[1]=='H'){

193                 modify(tid[x],y,1);

194             }else{

195                 mx = -INF;

196                 msum = 0;

197 

198                 while( top[x] != top[y] ){

199                     if( dep[ top[x] ] < dep[ top[y] ] )

200                         swap(x,y);

201                     ask( tid[ top[x] ] , tid[x] , 1 );

202                     x = fa[ top[x] ];

203                 }

204                 if(dep[x]>dep[y])

205                     swap(x,y);

206                 ask(tid[x],tid[y],1);

207 

208                 printf("%d\n",op[1]=='M'?mx:msum);

209             }

210         }

211     }

212 

213     return 0;

214 }

 

 

SPOJ 6779. Can you answer these queries VII

给定一棵点权树,支持以下两种操作:

  • 1 u v: 询问 u, v 路径上的最大子序列和。((允许不取)
  • 2 u v d: 将 u, v 路径上的所有点的点权都修改为 d。

Ural 1553. Caves and Tunnels

给定一个 n 个结点的带点权的树,要求维护以下两种操作:

  • I u d: 将结点 u 的权值 + d。
  • G u v: 询问 u、v 所在路径上点权的最大值。

spoj 2798 Query on a tree again!

给出一棵树,节点只有两种颜色,初始时颜色为白色。有两种操作:

 

  • 0 i :询问节点1到i的路径上第一个是黑色的节点,没有为-1.
  • 1 v:节点v颜色反置。

 

 

 

你可能感兴趣的:(count)