zoukankan      html  css  js  c++  java
  • BZOJ 2959: 长跑 lct 双联通分量 并查集 splay

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

    用两个并查集维护双联通分量的编号和合并。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<queue>
      7 using namespace std;
      8 const int maxn=800010;
      9 int n,m;
     10 int fa[maxn]={},ch[maxn][2]={},siz[maxn]={},val[maxn]={},rev[maxn];
     11 int shu[maxn]={}; 
     12 int sta[maxn]={},tail=0;
     13 int p[maxn]={},b[maxn]={};
     14 inline int read(){
     15     int x=0;int f=1;char ch=getchar();
     16     while(ch<'0'||ch>'9'){
     17         if(ch=='-')f=-1;
     18         ch=getchar();
     19     }
     20     while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     21     return x*f;
     22 }
     23 int findfa(int x){
     24     if(p[x]==x)return x;
     25     return p[x]=findfa(p[x]);
     26 }
     27 int bel(int x){
     28     if(b[x]==x)return x;
     29     return b[x]=bel(b[x]);
     30 }
     31 inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
     32 inline void updata(int x){ siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+val[x];}
     33 inline void rotate(int x){
     34     int y=fa[x];int fy=fa[y];
     35     int l=ch[y][0]==x?0:1;int r=l^1;
     36     if(!isroot(y)){
     37         if(ch[fy][0]==y)ch[fy][0]=x;
     38         else ch[fy][1]=x;
     39     }
     40     fa[ch[x][r]]=y;fa[y]=x;fa[x]=fy;
     41     ch[y][l]=ch[x][r]; ch[x][r]=y;
     42     updata(y);
     43 }
     44 inline void pushdown(int x){
     45     if(rev[x]){
     46         swap(ch[x][0],ch[x][1]);
     47         if(ch[x][0])rev[ch[x][0]]^=1;
     48         if(ch[x][1])rev[ch[x][1]]^=1;
     49         rev[x]=0;
     50     }
     51 }
     52 inline void splay(int x){
     53     x=bel(x);fa[x]=bel(fa[x]);
     54     int y,fy,w=x;
     55     sta[++tail]=w;
     56     while(!isroot(w)){
     57         fa[w]=bel(fa[w]);sta[++tail]=fa[w];
     58         fa[fa[w]]=bel(fa[fa[w]]);
     59         w=fa[w];
     60     }
     61     while(tail)pushdown(sta[tail--]);
     62     
     63     while(!isroot(x)){
     64         y=fa[x];fy=fa[y];
     65         if(!isroot(y)){
     66             if((ch[y][0]==x)^(ch[fy][0]==y))rotate(x);
     67             else rotate(y);
     68         }rotate(x);
     69     }updata(x);
     70 }
     71 inline void Access(int x){
     72     int y=0;
     73     while(x){
     74         x=bel(x);
     75         splay(x);ch[x][1]=y;
     76         updata(x);
     77         y=x;x=fa[x];
     78     }
     79 }
     80 inline void Reverse(int x){
     81     Access(x);splay(x);
     82     rev[x]^=1;
     83 }
     84 inline void Link(int x,int y){
     85     Reverse(x);fa[x]=y;
     86 }
     87 queue< int >q;
     88 inline void Merge(int x,int y){
     89     Reverse(y);Access(x);splay(x);
     90     int cnt=siz[x];
     91     q.push(x);
     92     while(!q.empty()){
     93         x=q.front();q.pop();
     94         if(ch[x][0])q.push(ch[x][0]);
     95         if(ch[x][1])q.push(ch[x][1]);
     96         b[bel(x)]=b[bel(y)];
     97         val[x]=siz[x]=fa[x]=ch[x][0]=ch[x][1]=0;
     98     }
     99     val[y]=siz[y]=cnt;fa[y]=0;
    100 }
    101 int main(){
    102     //freopen("now.in","r",stdin);
    103     n=read();m=read();;
    104     for(int i=1;i<=n;i++){val[i]=read();shu[i]=val[i];siz[i]=val[i];}
    105     for(int i=1;i<=n;i++)p[i]=i,b[i]=i;
    106     int op,x,y,xx,yy;
    107     for(int i=1;i<=m;i++){
    108         op=read();x=read();y=read();
    109         if(op==1){
    110             x=bel(x);y=bel(y);
    111             if(x!=y){
    112                 xx=findfa(x);yy=findfa(y);
    113                 if(xx==yy) Merge(x,y);
    114                 else {Link(x,y);p[xx]=yy;}
    115             }
    116         }
    117         else if(op==2){
    118             xx=bel(x);
    119             if(shu[x]!=y){
    120                 Access(xx);splay(xx);
    121                 siz[xx]+=y-shu[x];
    122                 val[xx]+=y-shu[x];
    123                 shu[x]=y;
    124             }
    125         }
    126         else{
    127             x=bel(x);y=bel(y);
    128             if(findfa(x)!=findfa(y)){
    129                 printf("-1
    ");
    130             }
    131             else{
    132                 Reverse(x);Access(y);splay(y);
    133                 printf("%d
    ",siz[y]);
    134             }
    135         }
    136     }
    137     return 0;
    138 }
    View Code

    注意一下双联通分量编号的维护

  • 相关阅读:
    好用的镜头站下载工具
    300+Jquery, CSS, MooTools 和 JS的导航菜单资源
    股票入门2
    MEF学习笔记(6):出口和元数据
    MEF学习笔记(5):迟延加载导出部件
    WinForm控件复杂数据绑定常用数据源(如:Dictionary)(对Combobox,DataGridView等控件DataSource赋值的多种方法)
    wpf 多线程绑定控件
    HTTP 错误 404.2 Not Found 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面
    ADODB.Stream 错误 '800a0bbc' 写入文件失败。
    'System.Windows.StaticResourceExtension' threw an exception
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8655318.html
Copyright © 2011-2022 走看看