zoukankan      html  css  js  c++  java
  • 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
    ",a[x]);
    214             else if(!connect(node[x][w],node[y][w])) puts("-1");
    215             else printf("%d
    ",querymax(node[x][w],node[y][w]));
    216         }
    217     }
    218     return 0;
    219 }

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

  • 相关阅读:
    lambda表达式
    各种模块化简介及演变过程
    filter-api文档
    RegExp正则表达式规则以及常用正则表达式
    各种循环遍历对比
    条件语句对比
    莫队小结
    停更公告
    POJ2728 Desert King
    笛卡尔树Cartesian Tree
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5293651.html
Copyright © 2011-2022 走看看