山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 2816: [ZJOI2012]网络(splay)

 

【题目链接】

 

    http://www.lydsy.com/JudgeOnline/problem.php?id=2816

   

【题意】

 

    给定一个无向图,满足条件:从一个节点出发的同色边不超过2条,且不存在同色环。要求提供修改节点权值,修改边的颜色,查询同色边c构成的图中u->v路径上节点的最大权值。

 

【思路】

 

    根据满足的条件,可以判断同色的图构成了若干条一条链。

    考虑使用splay维护这些链:

    对于每个图上的点建C个splay结点。这里需要splay提供将结点u旋转到根的操作,所以需要维护一个fa指针指向父亲,直接定位到结点u地址,先把该点到root路径上的所有标记下传,然后将u从下向上旋转至根。

    对于点修改:将u的所有颜色的结点修改。

    对于边修改:设oldc为原来边的颜色w为新颜色,uv为边的端点。将oldc颜色的u,v之间断开,然后把w颜色的uv连接。这里用到split和merge的操作。考虑merge,先将u,v splay至根,这时候一定满足u,v必有一个儿子为空(否则提前输出错误),如果出现u,v是相同儿子为空的情况,我们需要反转u的序列然后连接,所以splay还要维护一个rev的懒标记。

    对于查询:将u旋转到根,v旋转到u的一个儿子,假设位于d。u以及v以及v的d^1儿子构成了u..v之间的序列,这里可以加一个ori表示原来该节点代表的值,则答案为max{u->ori,v->ori,v->ch[d^1]->v}。

 

【代码】

 

  1 #include<map>
  2 #include<cmath>
  3 #include<queue>
  4 #include<vector>
  5 #include<cstdio>
  6 #include<cstring>
  7 #include<iostream>
  8 #include<algorithm>
  9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 11 using namespace std;
 12  
 13 typedef long long ll;
 14 typedef pair<int,int> edge;
 15 const int N = 5e4+10;
 16 const int M = 5e5+10;
 17  
 18 ll read() {
 19     char c=getchar();
 20     ll f=1,x=0;
 21     while(!isdigit(c)) {
 22         if(c=='-') f=-1; c=getchar();
 23     }
 24     while(isdigit(c))
 25         x=x*10+c-'0',c=getchar();
 26     return x*f;
 27 }
 28  
 29 struct Edge {
 30     int v,w,nxt;
 31 }e[M];
 32 int en=1,front[N];
 33 void adde(int u,int v,int w) 
 34 {
 35     e[++en]=(Edge){v,w,front[u]}; front[u]=en;
 36 }
 37  
 38 struct Node *null; 
 39 struct Node {
 40     Node *ch[2],*fa;
 41     int v,ori,rev;
 42     void init(int x) {
 43         v=ori=x; rev=0;
 44         ch[0]=ch[1]=fa=null;
 45     }
 46     void maintain() {
 47         v=max(ori,max(ch[0]->v,ch[1]->v));
 48     }
 49     void pushdown() {
 50         if(rev) {
 51             swap(ch[0],ch[1]);
 52             ch[0]->rev^=1,ch[1]->rev^=1;
 53             rev=0;
 54         }
 55     }
 56 }*node[N][20],nodepool[N*20];
 57 
 58 void rot(Node *o, int d) {
 59     Node *k=o->ch[d],*tmp=null;
 60     o->ch[d]=k->ch[d^1];
 61     if((tmp=k->ch[d^1])!=null) tmp->fa=o;
 62     k->ch[d^1]=o;
 63     if((tmp=o->fa)!=null) tmp->ch[tmp->ch[1]==o]=k;
 64     o->fa=k; k->fa=tmp;
 65 }
 66 void up_push(Node* u) {
 67     static Node* st[N]; int top=0;
 68     while(u!=null) {
 69         st[++top]=u;
 70         u=u->fa;
 71     }
 72     while(top)
 73         st[top--]->pushdown();
 74 }
 75 void splay(Node* u,Node* des=null) {
 76     up_push(u);
 77     Node *nf,*nff;
 78     while(u!=des && (nf=u->fa)!=des) {
 79         nff=nf->fa;
 80         if(nff==des) rot(nf,nf->ch[1]==u),nf->maintain();
 81         else {
 82             int d1=nf->ch[1]==u,d2=nff->ch[1]==nf;
 83             if(d1==d2) rot(nff,d2),rot(nf,d1);
 84             else rot(nf,d1),rot(nff,d2);
 85             nff->maintain(),nf->maintain();   
 86         }
 87     }
 88     u->maintain();
 89 }
 90 void reverse(Node* u) {
 91     swap(u->ch[0],u->ch[1]);
 92     u->ch[0]->rev^=1;
 93     u->ch[1]->rev^=1;
 94 }
 95 void split(Node* u,Node* v) {
 96     splay(u); splay(v,u);
 97     int d=u->ch[1]==v;
 98     u->ch[d]=null,v->fa=null;
 99     u->maintain();
100 }
101 void merge(Node* u,Node* v) {
102     splay(u); splay(v);
103     if(u->ch[1]==null&&v->ch[0]==null) u->ch[1]=v;
104     else if(u->ch[0]==null&&v->ch[1]==null) u->ch[0]=v;
105     else {
106         reverse(u);
107         if(u->ch[0]==null) u->ch[0]=v;
108         else u->ch[1]=v;
109     }
110     v->fa=u;
111     u->maintain();
112 }
113  
114 int n,m,C,K;
115 int col_cnt[N][20],col_vis[N][20],q[N],a[N];
116 map<pair<int,int>,int> mp;
117  
118 Node* build(int l,int r,Node* fa,int* q,int c) {
119     if(r<l) return null;
120     int mid=l+r>>1;
121     Node *u=node[q[mid]][c];
122     u->init(a[q[mid]]);
123     u->fa=fa;
124     u->ch[0]=build(l,mid-1,u,q,c);
125     u->ch[1]=build(mid+1,r,u,q,c);
126     u->maintain();
127     return u;
128 }
129 void bfs(int u,int c) {
130     static int q[M],f,r;
131     f=r=0;
132     col_vis[u][c]=1;
133     q[r++]=u;
134     while(f<r) {
135         int u=q[f++];
136         trav(u,i) if(e[i].w==c&&!col_vis[e[i].v][c]){
137             col_vis[e[i].v][c]=1;
138             q[r++]=e[i].v;
139             break;
140         }
141     }
142     build(0,r-1,null,q,c);
143 }
144  
145 int connect(Node* u,Node* v) {
146     splay(u); splay(v);
147     return u->fa!=null;
148 }
149 int querymax(Node* u,Node* v) {
150     splay(u),splay(v,u);
151     int d=v==u->ch[1];
152     return max(max(u->ori,v->ori),v->ch[d^1]->v);
153 }
154 
155 int main()
156 {
157     //freopen("in.in","r",stdin);
158     //freopen("out.out","w",stdout);
159     null=new Node();
160     n=read(),m=read(),C=read(),K=read();
161     FOR(i,1,n) a[i]=read();
162     FOR(i,1,m) {
163         int u=read(),v=read(),w=read();
164         w++;
165         adde(u,v,w),adde(v,u,w);
166         col_cnt[u][w]++;
167         col_cnt[v][w]++;
168         if(u>v) swap(u,v);
169         mp[make_pair(u,v)]=w;
170     }
171     FOR(i,1,n) FOR(j,1,C) {
172         node[i][j]=&nodepool[(i-1)*C+j-1];
173         node[i][j]->init(0);                                        //³õʼ»¯ÄÚ´æ³Ø
174     }
175     FOR(i,1,C) FOR(j,1,n)
176         if(!col_vis[j][i]&&col_cnt[j][i]==1) bfs(j,i);
177     FOR(i,1,K) {
178         int op=read(),x,y,w;
179         if(x>y) swap(x,y);
180         if(op==0) {
181             x=read(),y=read();
182             a[x]=y;
183             FOR(i,1,C) {
184                 splay(node[x][i]);
185                 node[x][i]->ori=node[x][i]->v=y;
186                 node[x][i]->maintain();
187             }
188         } else
189         if(op==1) {
190             x=read(),y=read();
191             if(x>y) swap(x,y);
192             w=read(); w++;
193             if(!mp.count(make_pair(x,y))) puts("No such edge.");
194             else {
195                 int old=mp[make_pair(x,y)];
196                 if(old==w) { puts("Success."); continue; }
197                 if(col_cnt[x][w]+1>2 || col_cnt[y][w]+1>2) puts("Error 1.");
198                 else if(connect(node[x][w],node[y][w])) puts("Error 2.");
199                 else {
200                     split(node[x][old],node[y][old]);
201                     merge(node[x][w],node[y][w]);
202                     --col_cnt[x][old];
203                     --col_cnt[y][old];
204                     ++col_cnt[x][w];
205                     ++col_cnt[y][w];
206                     mp[make_pair(x,y)]=w;
207                     puts("Success.");
208                 }
209             }
210         } else {
211             w=read(); w++; 
212             x=read(),y=read();
213             if(x==y) printf("%d\n",a[x]);
214             else if(!connect(node[x][w],node[y][w])) puts("-1");
215             else printf("%d\n",querymax(node[x][w],node[y][w]));
216         }
217     }
218     return 0;
219 }

 

P.S. 第一次写这种splay,代码借鉴别人的,又涨姿势了 ฅ(๑˙o˙๑)ฅ

 

posted on 2016-03-18 21:28  hahalidaxin  阅读(476)  评论(0编辑  收藏  举报