[POJ3237]树的维护

Posted 蒟蒻ZJO :-)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POJ3237]树的维护相关的知识,希望对你有一定的参考价值。

P1424 - [POJ3237]树的维护

Description

给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:
CHANGE i v:将第i条边的权值改成v。
NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。
QUERY a b:找出点a到点b路径上各边的最大权值。

Input

第一行有一个整数N(N<=10000)。
接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。
接下来是若干条指令(不超过10^5条),都按照上面所说的格式。
最后一行是"DONE".

Output

对每个“QUERY”指令,输出一行,即路径上各边的最大权值。

Sample Input

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

 

 

树链剖分,在线段树中维护一个区间最大和区间最小,
在进行取反操作时,将区间最小的相反数赋给最大,将区间最大值的相反数赋给最小,并标记
lazy数组。
另外,根节点在线段树中的值为0,但这不需要管,因为不会查询到根节点。

  1 #include<set>
  2 #include<map>
  3 #include<queue>
  4 #include<stack>
  5 #include<ctime>
  6 #include<cmath>
  7 #include<string>
  8 #include<vector>
  9 #include<cstdio>
 10 #include<cstdlib>
 11 #include<cstring>
 12 #include<iostream>
 13 #include<algorithm>
 14 #define maxn 10010
 15 #define ls o*2
 16 #define rs o*2+1
 17 #define mi int mid=(l+r)>>1
 18 using namespace std;
 19 struct data{
 20   int nex,to,w;
 21 }e[maxn*2];
 22 char s[10];
 23 int head[maxn],edge=0,n;
 24 int top[maxn],dis[maxn],dad[maxn],son[maxn],size[maxn],dfn[maxn],dfp[maxn],deep[maxn];
 25 int b[maxn*4],b1[maxn*4],lazy[maxn*4];
 26 void dfs1(int x,int fa){
 27   size[x]++;
 28   for(int i=head[x];i;i=e[i].nex){
 29     int u=e[i].to;
 30     if(u==fa) continue;
 31     dad[u]=x;
 32     dis[u]=e[i].w;
 33     deep[u]=deep[x]+1;
 34     dfs1(u,x);
 35     size[x]+=size[u];
 36     if(size[u]>size[son[x]]) son[x]=u;
 37   }
 38 }
 39 int de=0;
 40 void dfs2(int x,int fa){
 41   ++de;
 42   dfn[x]=de;dfp[de]=x;
 43   if(son[x]!=0) top[son[x]]=top[x],dfs2(son[x],x);
 44   for(int i=head[x];i;i=e[i].nex){
 45     int v=e[i].to;
 46     if(v==fa || v==son[x]) continue;
 47     top[v]=v;
 48     dfs2(v,x);
 49   }
 50 }
 51 void add(int from,int to,int w){
 52   e[++edge].nex=head[from];
 53   e[edge].to=to;
 54   e[edge].w=w;
 55   head[from]=edge;
 56 }
 57 void build(int o,int l,int r){
 58   if(l==r){b[o]=dis[dfp[l]];b1[o]=dis[dfp[l]];return;}
 59   mi;
 60   build(ls,l,mid);build(rs,mid+1,r);
 61   b[o]=min(b[ls],b[rs]);
 62   b1[o]=max(b1[ls],b1[rs]);
 63 }
 64 void down(int o){
 65   if(lazy[o]==-1){
 66     int tmp=b[ls];
 67     b[ls]=-b1[ls];b1[ls]=-tmp;
 68   }
 69   if(lazy[o]==-1){
 70     int tmp=b[rs];
 71     b[rs]=-b1[rs];b1[rs]=-tmp;
 72   }
 73   lazy[ls]*=lazy[o],lazy[rs]*=lazy[o];
 74   lazy[o]=1;
 75 }
 76 int query(int o,int l,int r,int u,int v){
 77   if(l!=r)down(o);
 78   if(l>=u && r<=v) return b1[o];
 79   if(l>v || r<u) return -1999999999;
 80   mi;
 81   if(v<=mid) return query(ls,l,mid,u,v);
 82   else if(u>mid) return query(rs,mid+1,r,u,v);
 83   else return max(query(ls,l,mid,u,mid),query(rs,mid+1,r,mid+1,v));
 84 }
 85 int lca(int x,int y){
 86   int ans=-1999999999;
 87   while(top[x]!=top[y]){
 88     if(deep[top[x]]>deep[top[y]]) ans=max(ans,query(1,1,n,dfn[top[x]],dfn[x])),x=dad[top[x]]; 
 89     else ans=max(ans,query(1,1,n,dfn[top[y]],dfn[y])),y=dad[top[y]];
 90   }
 91   if(deep[x]>deep[y]) swap(x,y);
 92   if(x!=y)
 93     ans=max(ans,query(1,1,n,dfn[x]+1,dfn[y]));
 94   return ans;
 95 }
 96 void negatee(int o,int l,int r,int u,int v){
 97   if(l!=r)down(o);
 98   if(l>=u && r<=v){
 99     int tmp=b[o];
100     b[o]=-b1[o];b1[o]=-tmp;
101     lazy[o]*=-1;
102     return;
103   }
104   mi;
105   if(v<=mid) negatee(ls,l,mid,u,v);
106   else if(u>mid) negatee(rs,mid+1,r,u,v);
107   else negatee(ls,l,mid,u,mid),negatee(rs,mid+1,r,mid+1,v);
108   b[o]=min(b[ls],b[rs]);
109   b1[o]=max(b1[ls],b1[rs]);
110 }
111 void lca1(int x,int y){
112   while(top[x]!=top[y]){
113     if(deep[top[x]]>deep[top[y]]) negatee(1,1,n,dfn[top[x]],dfn[x]),x=dad[top[x]];
114     else negatee(1,1,n,dfn[top[y]],dfn[y]),y=dad[top[y]];
115   }
116   if(deep[x]>deep[y]) swap(x,y);
117   if(x!=y)
118     negatee(1,1,n,dfn[x]+1,dfn[y]);
119 }
120 void change(int o,int l,int r,int k,int p){
121   if(l!=r) down(o);
122   if(l==r){b[o]=p,b1[o]=p;return;}
123   mi;
124   if(k<=mid)change(ls,l,mid,k,p);
125   else change(rs,mid+1,r,k,p);
126   b[o]=min(b[ls],b[rs]);
127   b1[o]=max(b1[ls],b1[rs]);
128 }
129 int main()
130 {
131   freopen("!.in","r",stdin);
132   freopen("!.out","w",stdout);
133   scanf("%d",&n);int x,y,z;
134   for(int i=1;i<=4*n;i++) lazy[i]=1;
135   for(int i=1;i<n;i++)
136     scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
137   top[1]=1,dad[1]=1;
138   dfs1(1,0);dfs2(1,0);build(1,1,n);
139   while(1){
140     scanf("%s",s);
141     if(s[0]==D) break;
142     if(s[0]==Q){
143       int x,y;
144       scanf("%d%d",&x,&y);
145       printf("%d\n",lca(x,y));
146     }
147     if(s[0]==C){
148       int x,y;scanf("%d%d",&x,&y);
149       int k1=e[2*x-1].to,k2=e[2*x].to;
150       int k;
151       if(deep[k1]>deep[k2]) k=k1;
152       else k=k2;
153       change(1,1,n,dfn[k],y);
154     }
155     if(s[0]==N){
156       int x,y;
157       scanf("%d%d",&x,&y);
158       lca1(x,y);
159     }
160   }
161   return 0;
162 }

 

 

以上是关于[POJ3237]树的维护的主要内容,如果未能解决你的问题,请参考以下文章

[POJ3237]树的维护

cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

POJ 3237 /// 树链剖分 线段树区间修改(*-1)

POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

poj3237 Tree

[POJ3237]Tree