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颜色反置。

 

 

 
posted @ 2013-08-24 18:09  yejinru  阅读(416)  评论(0编辑  收藏  举报