[SHOI2008]堵塞的交通traffic

我是萌萌的傳送門php

這題說白了就是一個支持加邊和刪邊的圖連通性維護,不過鑑於圖的特殊性,能夠直接線段樹(據說標算就是這個……)。ide

然而我人比較懶,不想思考怎麼線段樹,因而乎寫了一發分治並查集,1A我真是感動……spa

話說一時沒想起來怎麼寫能撤銷的按秩合併,因而乎寫了個隨機合併(反正指望複雜度都是logn的),代碼開頭那個玩意兒就是手寫的隨機數生成器……(我會說模數取998244353以後即便int有溢出也能保證循環節在一千萬以上嘛……)code

第一發分治並查集,又學會了一個新技能哈哈……blog

話說這份代碼在bzoj上被卡了,真是憂傷……get

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<map>
  6 using namespace std;
  7 const int maxn=100010;
  8 inline int randint(){
  9     static int a=151,b=24863,c=9788417,x=1089488183,p=998244353;
 10     x=a*x*x+b*x+c;x%=p;
 11     return x<0?(x=-x):x;
 12 }
 13 struct A{int u,v,tp;}a[maxn];
 14 void addedge(int,int,int);
 15 void addquery(int,int,int);
 16 void solve(int,int,int);
 17 int findroot(int);
 18 void mergeset(int,int,vector<int>&);
 19 int id[3][maxn],cnt=0,prt[maxn<<1],qu[maxn<<2],qv[maxn<<2];
 20 int n,m=1,x1,y1,x2,y2,x,y,s,t;
 21 vector<int>u[maxn<<2],v[maxn<<2],stk[maxn<<2];
 22 map<pair<int,int>,int>mp;
 23 char c[15];
 24 int main(){
 25     freopen("bzoj_1018.in","r",stdin);
 26     freopen("bzoj_1018.out","w",stdout);
 27     scanf("%d",&n);
 28     for(int i=1;i<=n;i++){
 29         id[1][i]=++cnt;
 30         id[2][i]=++cnt;
 31     }
 32     for(int i=1;i<=cnt;i++)prt[i]=i;
 33     for(int &i=m;scanf("%s",c)==1&&strcmp(c,"Exit");i++){
 34         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
 35         x=id[x1][y1];y=id[x2][y2];
 36         if(x>y)swap(x,y);
 37         a[i].u=x;a[i].v=y;
 38         if(!strcmp(c,"Open"))a[i].tp=1;
 39         else if(!strcmp(c,"Close"))a[i].tp=2;
 40         else a[i].tp=3;
 41     }
 42     for(int i=1;i<=m;i++){
 43         x=a[i].u;y=a[i].v;
 44         if(a[i].tp==1){
 45             if(!mp.count(make_pair(x,y)))mp[make_pair(x,y)]=i;
 46         }
 47         else if(a[i].tp==2){
 48             if(mp.count(make_pair(x,y))){
 49                 s=mp[make_pair(x,y)];
 50                 t=i;
 51                 addedge(1,m,1);
 52                 mp.erase(make_pair(x,y));
 53             }
 54         }
 55         else{
 56             t=i;
 57             addquery(1,m,1);
 58         }
 59     }
 60     for(map<pair<int,int>,int>::iterator it=mp.begin();it!=mp.end();it++){
 61         x=it->first.first;
 62         y=it->first.second;
 63         s=it->second;
 64         t=m;
 65         addedge(1,m,1);
 66     }
 67     solve(1,m,1);
 68     return 0;
 69 }
 70 void addedge(int l,int r,int rt){
 71     if(s<=l&&t>=r){
 72         u[rt].push_back(x);
 73         v[rt].push_back(y);
 74         return;
 75     }
 76     int mid=(l+r)>>1;
 77     if(s<=mid)addedge(l,mid,rt<<1);
 78     if(t>mid)addedge(mid+1,r,rt<<1|1);
 79 }
 80 void addquery(int l,int r,int rt){
 81     if(l==r){
 82         qu[rt]=x;
 83         qv[rt]=y;
 84         return;
 85     }
 86     qu[rt]|=x;
 87     int mid=(l+r)>>1;
 88     if(t<=mid)addquery(l,mid,rt<<1);
 89     else addquery(mid+1,r,rt<<1|1);
 90 }
 91 void solve(int l,int r,int rt){
 92     if(!qu[rt])return;
 93     for(int i=0;i<(int)u[rt].size();i++)mergeset(u[rt][i],v[rt][i],stk[rt]);
 94     if(l==r)printf(findroot(qu[rt])==findroot(qv[rt])?"Y\n":"N\n");
 95     else{
 96         int mid=(l+r)>>1;
 97         solve(l,mid,rt<<1);
 98         solve(mid+1,r,rt<<1|1);
 99     }
100     if(!stk[rt].empty())for(int i=(int)stk[rt].size()-1;i>=0;i--)prt[stk[rt][i]]=stk[rt][i];
101 }
102 int findroot(int x){
103     while(prt[x]!=x)x=prt[x];
104     return x;
105 }
106 void mergeset(int x,int y,vector<int>&a){
107     x=findroot(x);y=findroot(y);
108     if(x==y)return;
109     if(randint()&1)swap(x,y);
110     prt[x]=y;
111     a.push_back(x);
112 }
View Code

不知道該加什麼分類了,反正是對時間建線段樹,加到CDQ分治裏算了……string

相關文章
相關標籤/搜索