Cogs 1583. [POJ3237]树的维护 LCT,树链剖分

题目:http://cojs.tk/cogs/problem/problem.php?pid=1583

1583. [POJ3237]树的维护

★★★☆   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比
时间限制:5 s   内存限制:128 MB

【题目描述】

给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:

CHANGE i v:将第i条边的权值改成v。

NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。

QUERY a b:找出点a到点b路径上各边的最大权值。

【输入格式】

输入文件的第一行有一个整数N(N<=10000)。

接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。

接下来是若干条指令(不超过10^5条),都按照上面所说的格式。

输入文件的最后一行是"DONE".

【输出格式】

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

【样例输入】

3

1 2 1

2 3 2

QUERY 1 2

CHANGE 1 3

QUERY 1 2

DONE

【样例输出】

1

3

【提示】

这里的输入输出格式和POJ上原题略有不同。

【来源】

POJ 3237 Tree

题解:

LCT维护一下最大值和最小值,当要变为相反数时,把 最大值变为原来的最小值的相反数,最小值变为原来最大值的相反数 即可。。。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define INF 1e9
  4 #define MAXN 10010
  5 struct node
  6 {
  7     int left,right,mx,mn,val;
  8 }tree[2*MAXN];
  9 int rev[2*MAXN],tag[2*MAXN],father[2*MAXN],Stack[2*MAXN],n;
 10 int read()
 11 {
 12     int s=0,fh=1;char ch=getchar();
 13     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
 14     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
 15     return s*fh;
 16 }
 17 int isroot(int x)
 18 {
 19     return tree[father[x]].left!=x&&tree[father[x]].right!=x;
 20 }
 21 void pushdown(int x)
 22 {
 23     int l=tree[x].left,r=tree[x].right;
 24     if(rev[x]!=0)
 25     {
 26         rev[x]^=1;rev[l]^=1;rev[r]^=1;
 27         swap(tree[x].left,tree[x].right);
 28     }
 29     if(tag[x]!=0)
 30     {
 31         tag[x]^=1;tag[l]^=1;tag[r]^=1;
 32         tree[l].val=-tree[l].val;
 33         tree[r].val=-tree[r].val;
 34         swap(tree[l].mx,tree[l].mn);
 35         tree[l].mx=-tree[l].mx;tree[l].mn=-tree[l].mn;
 36         swap(tree[r].mx,tree[r].mn);
 37         tree[r].mx=-tree[r].mx;tree[r].mn=-tree[r].mn;
 38     }
 39 }
 40 void pushup(int x)
 41 {
 42     int l=tree[x].left,r=tree[x].right;
 43     tree[x].mx=max(tree[l].mx,tree[r].mx);
 44     if(x>n)tree[x].mx=max(tree[x].mx,tree[x].val);
 45     tree[x].mn=min(tree[l].mn,tree[r].mn);
 46     if(x>n)tree[x].mn=min(tree[x].mn,tree[x].val);
 47 }
 48 void rotate(int x)
 49 {
 50     int y=father[x],z=father[y];
 51     if(!isroot(y))
 52     {
 53         if(tree[z].left==y)tree[z].left=x;
 54         else tree[z].right=x;
 55     }
 56     if(tree[y].left==x)
 57     {
 58         father[x]=z;father[y]=x;tree[y].left=tree[x].right;tree[x].right=y;father[tree[y].left]=y;
 59     }
 60     else
 61     {
 62         father[x]=z;father[y]=x;tree[y].right=tree[x].left;tree[x].left=y;father[tree[y].right]=y;
 63     }
 64     pushup(y);pushup(x);
 65 }
 66 void splay(int x)
 67 {
 68     int top=0,i,y,z;Stack[++top]=x;
 69     for(i=x;!isroot(i);i=father[i])Stack[++top]=father[i];
 70     for(i=top;i>=1;i--)pushdown(Stack[i]);
 71     while(!isroot(x))
 72     {
 73         y=father[x],z=father[y];
 74         if(!isroot(y))
 75         {
 76             if((tree[y].left==x)^(tree[z].left==y))rotate(x);
 77             else rotate(y);
 78         }
 79         rotate(x);
 80     }
 81 }
 82 void access(int x)
 83 {
 84     int last=0;
 85     while(x!=0)
 86     {
 87         splay(x);
 88         tree[x].right=last;pushup(x);
 89         last=x;x=father[x];
 90     }
 91 }
 92 void makeroot(int x)
 93 {
 94     access(x);splay(x);rev[x]^=1;
 95 }
 96 void link(int u,int v)
 97 {
 98     makeroot(u);father[u]=v;splay(u);
 99 }
100 void cut(int u,int v)
101 {
102     makeroot(u);access(v);splay(v);father[u]=tree[v].left=0;
103 }
104 int findroot(int x)
105 {
106     access(x);splay(x);
107     while(tree[x].left!=0)x=tree[x].left;
108     return x;
109 }
110 int main()
111 {
112     freopen("maintaintree.in","r",stdin);
113     freopen("maintaintree.out","w",stdout);
114     int i,a,b,c;
115     char fh[8];
116     n=read();
117     for(i=0;i<=2*n;i++)tree[i].mx=-INF,tree[i].mn=INF;
118     for(i=1;i<n;i++)
119     {
120         a=read();b=read();c=read();
121         tree[n+i].mx=tree[n+i].mn=tree[n+i].val=c;
122         link(a,n+i);link(n+i,b);
123     }
124     while(1)
125     {
126         scanf("\n%s",fh);
127         if(fh[0]=='D')break;
128         if(fh[0]=='Q')
129         {
130             a=read();b=read();
131             makeroot(a);access(b);splay(b);
132             printf("%d\n",tree[b].mx);
133         }
134         else if(fh[0]=='C')
135         {
136             a=read();b=read();
137             makeroot(n+a);tree[n+a].mn=tree[n+a].mx=tree[n+a].val=b;
138         }
139         else
140         {
141             a=read();b=read();
142             makeroot(a);access(b);splay(b);
143             tag[b]^=1;
144             swap(tree[b].mx,tree[b].mn);
145             tree[b].val=-tree[b].val;
146             tree[b].mx=-tree[b].mx;
147             tree[b].mn=-tree[b].mn;
148         }
149     }
150     fclose(stdin);
151     fclose(stdout);
152     return 0;
153 }
View Code

 2016.3.24

补一发树链剖分:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 10010
  4 #define INF 1e9
  5 struct node
  6 {
  7     int begin,end,value,next;
  8 }edge[2*MAXN];
  9 struct NODE
 10 {
 11     int left,right,mx,mn,tag;
 12 }tree[5*MAXN];
 13 int cnt,Head[MAXN],n,size[MAXN],deep[MAXN],P[MAXN][14],pos[MAXN],belong[MAXN],id[MAXN],vv[MAXN],U[MAXN],V[MAXN],VAL[MAXN],SIZE;
 14 bool vis[MAXN];
 15 void addedge(int bb,int ee,int vv)
 16 {
 17     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
 18 }
 19 void addedge1(int bb,int ee,int vv)
 20 {
 21     addedge(bb,ee,vv);addedge(ee,bb,vv);
 22 }
 23 int read()
 24 {
 25     int s=0,fh=1;char ch=getchar();
 26     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
 27     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
 28     return s*fh;
 29 }
 30 void dfs1(int u)
 31 {
 32     int i,v;
 33     size[u]=1;vis[u]=true;
 34     for(i=Head[u];i!=-1;i=edge[i].next)
 35     {
 36         v=edge[i].end;
 37         if(vis[v]==false)
 38         {
 39             deep[v]=deep[u]+1;
 40             P[v][0]=u;
 41             dfs1(v);
 42             size[u]+=size[v];
 43         }
 44     }
 45 }
 46 void Ycl()
 47 {
 48     int i,j;
 49     for(j=1;(1<<j)<=n;j++)
 50     {
 51         for(i=1;i<=n;i++)
 52         {
 53             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
 54         }
 55     }
 56 }
 57 void dfs2(int u,int chain)
 58 {
 59     int k=0,i,v;
 60     pos[u]=++SIZE;belong[u]=chain;
 61     for(i=Head[u];i!=-1;i=edge[i].next)
 62     {
 63         v=edge[i].end;
 64         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
 65     }
 66     if(k==0)return;
 67     dfs2(k,chain);
 68     for(i=Head[u];i!=-1;i=edge[i].next)
 69     {
 70         v=edge[i].end;
 71         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
 72     }
 73 }
 74 int LCA(int x,int y)
 75 {
 76     int i,j;
 77     if(deep[x]<deep[y])swap(x,y);
 78     for(i=0;(1<<i)<=deep[x];i++);i--;
 79     for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j];
 80     if(x==y)return x;
 81     for(j=i;j>=0;j--)
 82     {
 83         if(P[x][j]!=-1&&P[x][j]!=P[y][j])
 84         {
 85             x=P[x][j];
 86             y=P[y][j];
 87         }
 88     }
 89     return P[x][0];
 90 }
 91 void Pushup(int k)
 92 {
 93     tree[k].mx=max(tree[k*2].mx,tree[k*2+1].mx);
 94     tree[k].mn=min(tree[k*2].mn,tree[k*2+1].mn);
 95 }
 96 void Pushdown(int k)
 97 {
 98     int l=k*2,r=k*2+1;
 99     if(tree[k].tag!=0)
100     {
101         tree[k].tag^=1;tree[l].tag^=1;tree[r].tag^=1;
102         swap(tree[l].mn,tree[l].mx);
103         tree[l].mn=-tree[l].mn;tree[l].mx=-tree[l].mx;
104         swap(tree[r].mn,tree[r].mx);
105         tree[r].mn=-tree[r].mn;tree[r].mx=-tree[r].mx;
106     }
107 }
108 void Build(int k,int l,int r)
109 {
110     tree[k].left=l;tree[k].right=r;tree[k].mx=-INF;tree[k].mn=INF;tree[k].tag=0;
111     if(l==r)
112     {
113         tree[k].mx=tree[k].mn=vv[l];
114         return;
115     }
116     int mid=(l+r)/2;
117     Build(k*2,l,mid);Build(k*2+1,mid+1,r);
118     Pushup(k);
119 }
120 void Change(int k,int lr,int C)
121 {
122     if(tree[k].left==tree[k].right){tree[k].mx=tree[k].mn=C;return;}
123     Pushdown(k);
124     int mid=(tree[k].left+tree[k].right)/2;
125     if(lr<=mid)Change(k*2,lr,C);
126     else Change(k*2+1,lr,C);
127     Pushup(k);
128 }
129 int Query_max(int k,int l,int r)
130 {
131     if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mx;
132     Pushdown(k);
133     int mid=(tree[k].left+tree[k].right)/2;
134     if(r<=mid)return Query_max(k*2,l,r);
135     else if(l>mid)return Query_max(k*2+1,l,r);
136     else return max(Query_max(k*2,l,mid),Query_max(k*2+1,mid+1,r));
137 }
138 int Solve_max(int x,int f)
139 {
140     int MAX=-INF;
141     while(belong[x]!=belong[f])
142     {
143         MAX=max(MAX,Query_max(1,pos[belong[x]],pos[x]));
144         x=P[belong[x]][0];
145     }
146     if(x!=f)MAX=max(MAX,Query_max(1,pos[f]+1,pos[x]));
147     return MAX;
148 }
149 void Negate(int k,int l,int r)
150 {
151     if(l<=tree[k].left&&tree[k].right<=r/*tree[k].left==tree[k].right*/)
152     {
153         swap(tree[k].mn,tree[k].mx);
154         tree[k].mn=-tree[k].mn;tree[k].mx=-tree[k].mx;
155         tree[k].tag^=1;
156         return;
157     }
158     Pushdown(k);
159     int mid=(tree[k].left+tree[k].right)/2;
160     if(r<=mid)Negate(k*2,l,r);
161     else if(l>mid)Negate(k*2+1,l,r);
162     else {Negate(k*2,l,mid);Negate(k*2+1,mid+1,r);}
163     Pushup(k);
164 }
165 void Solve_negate(int x,int f)
166 {
167     while(belong[x]!=belong[f])
168     {
169         Negate(1,pos[belong[x]],pos[x]);
170         x=P[belong[x]][0];
171     }
172     if(x!=f)Negate(1,pos[f]+1,pos[x]);
173 }
174 int main()
175 {
176     freopen("maintaintree.in","r",stdin);
177     freopen("maintaintree.out","w",stdout);
178     int i,I,W,bb,ee,lca;
179     char fh[8];
180     n=read();
181     memset(Head,-1,sizeof(Head));cnt=1;
182     for(i=1;i<n;i++)
183     {
184         U[i]=read();V[i]=read();VAL[i]=read();
185         addedge1(U[i],V[i],VAL[i]);
186     }
187     memset(P,-1,sizeof(P));SIZE=0;
188     dfs1(1);Ycl();
189     dfs2(1,1);
190     for(i=1;i<n;i++)
191     {
192         if(deep[U[i]]>deep[V[i]])id[i]=U[i];
193         else id[i]=V[i];
194     }
195     for(i=1;i<n;i++)vv[pos[id[i]]]=VAL[i];
196     Build(1,1,n);
197     while(1)
198     {
199         scanf("\n%s",fh);
200         if(fh[0]=='D')break;
201         if(fh[0]=='C')
202         {
203             I=read();W=read();
204             Change(1,pos[id[I]],W);
205         }
206         else if(fh[0]=='Q')
207         {
208             bb=read();ee=read();
209             lca=LCA(bb,ee);
210             printf("%d\n",max(Solve_max(bb,lca),Solve_max(ee,lca)));
211         }
212         else
213         {
214             bb=read();ee=read();
215             lca=LCA(bb,ee);
216             Solve_negate(bb,lca);
217             Solve_negate(ee,lca);
218         }
219     }
220     fclose(stdin);
221     fclose(stdout);
222     return 0;
223 }

 

posted @ 2016-03-15 12:41  微弱的世界  阅读(250)  评论(0编辑  收藏  举报