您的位置:首页 > 其它

【BZOJ】【P1453】【WC2005】【Dface双面棋盘】【题解】【线段树+并查集】

2014-12-22 20:48 369 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1453

用线段树维护每行,每个节点套并查集,记录最上方和最下方的联通性,暴力合并暴力修改并查集,记录答案,

并查集的合并比较恶心,我yy了很久……(请读者自行思考)

我用并查集中的1..n表示上方,n+1..2n表示下方,合并时2n+1..4n用于右侧的上下方并查集

Code:

#include<bits/stdc++.h>
using namespace std;
struct ufset{
vector<int>fa;
int n;
void init(int _n){n=_n;fa.resize(n+1);for(int i=1;i<=n;++i)fa[i]=i;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y){fa[find(x)]=find(y);}
bool same(int x,int y){return find(x)==find(y);}
int& at(int x){return fa[x];}
};
int n,m,a[201][201];
int mp[801];
struct sgt{
struct node{
ufset U;
int w,b;
int& at(int x){return U.at(x);}
node(){w=b=0;}
}t[201<<2];
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
void rz(int i,int l,int r){
int L=i<<1,R=i<<1|1,mid=(l+r)>>1;
t[i].b=t[L].b+t[R].b;
t[i].w=t[L].w+t[R].w;
t[i].U.init(n<<2);
for(int j=1;j<=2*n;j++){
t[i].U.merge(j,t[L].U.find(j));
t[i].U.merge(j+2*n,t[R].U.find(j)+2*n);
}
for(int j=1;j<=n;j++){
if(a[mid][j]==a[mid+1][j]){
if(t[i].U.same(j+n,j+n*2))continue;
t[i].U.merge(j+n,j+n*2);
t[i].w-=a[mid][j]==0;
t[i].b-=a[mid][j]==1;
}
}
for(int j=1;j<=4*n;j++)t[i].U.find(j);
memset(mp,0,sizeof mp);
for(int j=1;j<=n;j++){
if(!mp[t[i].at(j)]){
mp[t[i].at(j)]=j;
t[i].at(j)=j;
}else t[i].at(j)=mp[t[i].at(j)];
}
for(int j=n*3+1;j<=4*n;j++){
if(!mp[t[i].at(j)]){
mp[t[i].at(j)]=j-n*2;
t[i].at(j)=j-2*n;
}else t[i].at(j)=mp[t[i].at(j)];
}
for(int j=1;j<=n;j++)t[i].U.at(j+n)=t[i].U.at(j+3*n);
for(int j=2*n+1;j<=4*n;j++)t[i].U.at(j)=j;
}
void build(int i,int l,int r){
if(l==r){
t[i].U.init(n<<2);
t[i].w=a[l][1]==0;
t[i].b=a[l][1]==1;
t[i].U.merge(1+n,1);
for(int j=2;j<=n;j++){
t[i].U.merge(j+n,j);
if(a[l][j]==a[l][j-1]){
t[i].U.merge(j,j-1);
}else t[i].w+=a[l][j]==0,
t[i].b+=a[l][j]==1;
}
return;
}int mid=(l+r)>>1;
build(lson);build(rson);
rz(i,l,r);
}
void Change(int i,int l,int r,int ps){
if(l==r){
t[i].U.init(n<<2);
t[i].w=a[l][1]==0;
t[i].b=a[l][1]==1;
t[i].U.merge(1+n,1);
for(int j=2;j<=n;j++){
t[i].U.merge(j+n,j);
if(a[l][j]==a[l][j-1]){
t[i].U.merge(j,j-1);
}else t[i].w+=a[l][j]==0,
t[i].b+=a[l][j]==1;
}
return;
}int mid=(l+r)>>1;
if(ps<=mid)Change(lson,ps);
else Change(rson,ps);
rz(i,l,r);
}
int Qb(){return t[1].b;}
int Qw(){return t[1].w;}
}T;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
T.build(1,1,n);
scanf("%d",&m);
while(m--){
int x,y;scanf("%d%d",&x,&y);
a[x][y]^=1;
T.Change(1,1,n,x);
printf("%d %d\n",T.Qb(),T.Qw());
}return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj