码迷,mamicode.com
首页 > 其他好文 > 详细

(ZJOI2008)BZOJ1036 树的统计

时间:2016-05-15 00:21:22      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

题意:维护树上一条路径上的结点权值最大值或和

 

正解:树链剖分+线段树

 

没什么好说的,链剖裸题。先树链剖分再根据访问次序建立线段树,用线段树动态维护。

模板题练手。

 

  1 //It is made by jump~
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <algorithm>
  8 using namespace std;
  9 typedef long long LL;
 10 const int MAXN = 30011;
 11 const int inf = (1<<30);
 12 int n;
 13 int total,ecnt;
 14 int U,VV;
 15 int a[MAXN];
 16 int id[MAXN],pre[MAXN];
 17 int top[MAXN],siz[MAXN],zhongerzi[MAXN],father[MAXN],deep[MAXN];
 18 int next[MAXN*2],to[MAXN*2],first[MAXN];
 19 char ch[8];
 20 
 21 struct node{
 22     int l,r;
 23     int _max;int _sum;
 24 }jump[MAXN*4];
 25 
 26 void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
 27 
 28 int getint()
 29 {
 30        int w=0,q=0;
 31        char c=getchar();
 32        while((c<0 || c>9) && c!=-) c=getchar();
 33        if (c==-)  q=1, c=getchar();
 34        while (c>=0 && c<=9) w=w*10+c-0, c=getchar();
 35        return q ? -w : w;
 36 }
 37 
 38 void build(int root,int l,int r){
 39     jump[root].l=l;jump[root].r=r;
 40     if(jump[root].l==jump[root].r) {
 41         jump[root]._sum=jump[root]._max=a[ pre[l] ];
 42         return ;
 43     }
 44     int lc=root*2,rc=root*2+1;
 45     int mid=l+(r-l)/2;
 46     build(lc,l,mid); build(rc,mid+1,r);
 47     jump[root]._sum=jump[lc]._sum+jump[rc]._sum;
 48     jump[root]._max=max(jump[lc]._max,jump[rc]._max);
 49 }
 50 
 51 void dfs1(int u,int fa){
 52     siz[u]=1;
 53     for(int i=first[u];i;i=next[i]) {
 54         int v=to[i];
 55         if(v!=fa) {
 56             father[v]=u;
 57             deep[v]=deep[u]+1;
 58             dfs1(v,u);
 59             siz[u]+=siz[v];
 60             if(siz[v]>siz[ zhongerzi[u] ]) zhongerzi[u]=v;
 61         }
 62     }
 63 }
 64 
 65 void dfs2(int u,int fa){
 66     id[u]=++total; pre[total]=u;
 67     if(zhongerzi[u]) top[zhongerzi[u]]=top[u],dfs2(zhongerzi[u],u);
 68     for(int i=first[u];i;i=next[i]) {
 69         int v=to[i];
 70         if(v==fa || v==zhongerzi[u]) continue;
 71         top[v]=v;
 72         dfs2(v,u);
 73     }
 74 }
 75 
 76 int query_sum(int root,int x,int y){
 77     if(jump[root].l>=x && jump[root].r<=y) return jump[root]._sum;
 78     int da=0;
 79     int mid=jump[root].l+(jump[root].r-jump[root].l)/2;
 80     int lc=root*2,rc=root*2+1;
 81     if(x<=mid) da+=query_sum(lc,x,y);
 82     if(y>mid) da+=query_sum(rc,x,y);
 83     return da;
 84 }
 85 
 86 
 87 int query_max(int root,int x,int y){
 88     if(jump[root].l>=x && jump[root].r<=y) return jump[root]._max;
 89     int da=-inf;
 90     int mid=jump[root].l+(jump[root].r-jump[root].l)/2;
 91     int lc=root*2,rc=root*2+1;
 92     if(x<=mid) da=max(da,query_max(lc,x,y));
 93     if(y>mid) da=max(da,query_max(rc,x,y));
 94     return da;
 95 }
 96 
 97 int find_max(int x,int y){
 98     int f1=top[x],f2=top[y];
 99     int daan=-inf;
100     while(f1!=f2){
101             if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
102             daan=max(daan,query_max(1,id[f1],id[x]));
103             x=father[f1];
104             f1=top[x];
105     }
106     if(deep[x]<deep[y]) swap(x,y);
107     daan=max(daan,query_max(1,id[y],id[x]));
108     return daan;
109 }
110 
111 int find_sum(int x,int y){
112     int f1=top[x],f2=top[y];
113     int daan=0;
114     while(f1!=f2){
115           if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
116           daan+=query_sum(1,id[f1],id[x]);
117           x=father[f1]; f1=top[x];
118     }
119     if(deep[x]<deep[y]) swap(x,y);
120     daan+=query_sum(1,id[y],id[x]);
121     return daan;
122 }
123 
124 void update(int root,int o,int add){
125     if(jump[root].l==jump[root].r){
126         jump[root]._sum+=add;
127         jump[root]._max+=add;return ;
128     }
129     int lc=root*2,rc=root*2+1;
130     int mid=jump[root].l+(jump[root].r-jump[root].l)/2;
131     if(o<=mid) update(lc,o,add); else update(rc,o,add);
132     jump[root]._sum=jump[lc]._sum+jump[rc]._sum;
133     jump[root]._max=max(jump[lc]._max,jump[rc]._max);
134 }
135 
136 int main()
137 {
138   n=getint();
139   int x,y;
140   for(int i=1;i<n;i++){
141       x=getint();y=getint();
142       next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; 
143       next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; 
144    }
145 
146   deep[1]=1;  dfs1(1,0);
147   top[1]=1;  dfs2(1,0);
148 
149   for(int i=1;i<=n;i++) a[i]=getint();
150   build(1,1,n);
151   int Q=getint();
152 
153   for(int i=1;i<=Q;i++){
154       scanf("%s",ch);
155       if(ch[1]==M){  
156           printf("%d\n",find_max(x,y));
157       }
158       else if(ch[1]==S){
159           x=getint();y=getint();
160           printf("%d\n",find_sum(x,y));
161       }
162       else{
163           U=getint();VV=getint();
164           update(1,id[U],VV-a[U]);a[U]=VV;
165       }
166    }
167   return 0;
168 }

 

(ZJOI2008)BZOJ1036 树的统计

标签:

原文地址:http://www.cnblogs.com/ljh2000-jump/p/5493985.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!