POJ3237 (树链剖分+线段树)

Problem Tree (POJ3237)

题目大意

  给定一颗树,有边权。

  要求支持三种操作:

    操作一:更改某条边的权值。

    操作二:将某条路径上的边权取反。

    操作三:询问某条路径上的最大权值。

解题分析

  树链剖分+线段树。练手题。

参考程序

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 #define V 100008
  8 #define E 200008
  9 #define lson l,m,rt<<1
 10 #define rson m+1,r,rt<<1|1
 11 #define INF 2000000000
 12 
 13 int cnt,n;
 14 int size[V],dep[V],fa[V],son[V],top[V],w[V],rk[V],a[V];
 15 
 16 struct line{
 17     int u,v,w,nt;
 18 }eg[E];
 19 int lt[V],sum;
 20 
 21 void adt(int u,int v,int w){
 22     eg[++sum].u=u; eg[sum].v=v; eg[sum].w=w; eg[sum].nt=lt[u]; lt[u]=sum;
 23 }
 24 void add(int u,int v,int w){
 25     adt(u,v,w); adt(v,u,w);
 26 }
 27 
 28 struct segment_tree{
 29     // 单点修改 区间取反 区间询问
 30     int mx[V<<2],mn[V<<2],lazy[V<<2];
 31     void pushup(int rt){
 32         mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
 33         mn[rt]=min(mn[rt<<1],mn[rt<<1|1]);
 34     }
 35     void pushdown(int rt){
 36         if (lazy[rt]){
 37             lazy[rt<<1]^=1;
 38             lazy[rt<<1|1]^=1;    
 39             int t=mx[rt<<1];
 40             mx[rt<<1]=-mn[rt<<1];
 41             mn[rt<<1]=-t;
 42             t=mx[rt<<1|1];
 43             mx[rt<<1|1]=-mn[rt<<1|1];
 44             mn[rt<<1|1]=-t;
 45             lazy[rt]=0;
 46         }
 47     }
 48     void build(int l,int r,int rt){
 49         lazy[rt]=0; 
 50         if (l==r){
 51             mn[rt]=mx[rt]=a[rk[l]];
 52             return;
 53         }
 54         int m=(l+r)/2;
 55         build(lson);
 56         build(rson);
 57         pushup(rt);
 58     }
 59     void update_1(int x,int val,int l,int r,int rt){
 60         if (l==r){
 61             mx[rt]=val;
 62             mn[rt]=val;
 63             return;
 64         }
 65         pushdown(rt);
 66         int m=(l+r)/2;
 67         if (x <= m) update_1(x,val,lson);
 68         if (m <  x) update_1(x,val,rson); 
 69         pushup(rt);
 70     }
 71     void  update_2(int L,int R,int l,int r,int rt){
 72         if (L<=l && r<=R){    
 73             int t=mx[rt];
 74             mx[rt]=-mn[rt];
 75             mn[rt]=-t;
 76             lazy[rt]^=1;
 77             return;
 78         }
 79         pushdown(rt);
 80         int m=(l+r)/2;
 81         if (L <= m) update_2(L,R,lson);
 82         if (m <  R) update_2(L,R,rson); 
 83         pushup(rt);
 84     }
 85     int query(int L,int R,int l,int r,int rt){
 86         if (L<=l && r<=R){
 87             return mx[rt];
 88         }
 89         pushdown(rt);
 90         int m=(l+r)/2;
 91         int res=-INF;
 92         if (L <= m) res=max(res,query(L,R,lson));
 93         if (m <  R) res=max(res,query(L,R,rson));  
 94         return res;
 95     }
 96 }T;
 97 
 98 void dfs_1(int u){
 99     dep[u]=dep[fa[u]]+1; size[u]=1; son[u]=0;
100     for (int i=lt[u];i;i=eg[i].nt){
101         int v=eg[i].v;
102         if (v==fa[u]) continue;
103         a[v]=eg[i].w;
104         fa[v]=u;
105         dfs_1(v);
106         size[u]+=size[v];
107         if (size[v]>size[son[u]]) son[u]=v;
108     }
109 }
110 void dfs_2(int u,int tp){ 
111     top[u]=tp; w[u]=++cnt; rk[cnt]=u;
112     if (son[u]) dfs_2(son[u],tp);
113     for (int i=lt[u];i;i=eg[i].nt){
114         int v=eg[i].v;
115         if (v==fa[u] || v==son[u]) continue;
116         dfs_2(v,v);
117     }
118 }
119 void find_1(int x,int y){
120     int res=-INF;
121     while (top[x]!=top[y]){
122         if (dep[top[x]]<dep[top[y]]) swap(x,y);
123         res=max(res,T.query(w[top[x]],w[x],1,n,1));
124         x=fa[top[x]];
125     }
126     if (dep[x]>dep[y]) swap(x,y);
127     res=max(res,T.query(w[x]+1,w[y],1,n,1));
128     printf("%d\n",res);
129 }
130 void find_2(int x,int y){
131     while (top[x]!=top[y]){
132         if (dep[top[x]]<dep[top[y]]) swap(x,y);
133         T.update_2(w[top[x]],w[x],1,n,1);
134         x=fa[top[x]];
135     }
136     if (dep[x]>dep[y]) swap(x,y);
137     T.update_2(w[x]+1,w[y],1,n,1);
138 }
139 
140 int main(){
141     int tt;
142     scanf("%d",&tt);
143     while (tt--){
144         sum=1; cnt=0;
145         memset(lt,0,sizeof(lt));
146         scanf("%d",&n);
147         for (int i=1;i<n;i++){
148             int u,v,w;
149             scanf("%d %d %d",&u,&v,&w);
150             add(u,v,w);
151         }    
152         scanf("\n");
153         dfs_1(1);
154         dfs_2(1,1);
155         T.build(1,n,1);
156         char s[10];
157         for (scanf("%s",s);strcmp(s,"DONE")!=0;scanf("%s",s)){    
158             int x,y;
159             scanf("%d %d\n",&x,&y);
160             if (strcmp(s,"QUERY")==0){
161                 find_1(x,y);
162             }
163             if (strcmp(s,"CHANGE")==0){
164                 int u=eg[x*2].u , v=eg[x*2].v;
165                 if (dep[u]<dep[v]) T.update_1(w[v],y,1,n,1);
166                     else T.update_1(w[u],y,1,n,1);
167             }
168             if (strcmp(s,"NEGATE")==0){
169                 find_2(x,y);
170             }
171         }    
172     }
173 }
View Code

 

posted @ 2016-08-02 21:58  rpSebastian  阅读(224)  评论(0编辑  收藏  举报