標籤:線段 ble close isp 分享 ras images algorithm stdout
我是萌萌的傳送門
這題說白了就是一個支援加邊和刪邊的圖連通性維護,不過鑒於圖的特殊性,可以直接線段樹(聽說標算就是這個……)。
然而我人比較懶,不想思考怎麼線段樹,於是乎寫了一發分治並查集,1A我真是感動……
話說一時沒想起來怎麼寫能撤銷的按秩合并,於是乎寫了個隨機合并(反正期望複雜度都是logn的),代碼開頭那個玩意兒就是手寫的隨機數產生器……(我會說模數取998244353之後即使int有溢出也能保證迴圈節在一千萬以上嘛……)
第一發分治並查集,又學會了一個新技能哈哈……
話說這份代碼在bzoj上被卡了,真是憂傷……
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分治裡算了……
[SHOI2008]堵塞的交通traffic