码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1453 双面棋盘

时间:2018-02-06 01:18:58      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:联通   黑白   har   closed   int   ide   math   names   ==   

题目大意:

一个黑白方格图 

支持单点修改 查询黑色与白色联通快个数

思路:

可以把每一行压为一个点

使用线段树来维护

然后两行合并的时候使用并查集来合并

技术分享图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #define ll long long
11 #define inf 2139062143
12 #define MAXN 220
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch==-) f=-1;ch=getchar();}
18     while(isdigit(ch)) x=x*10+ch-0,ch=getchar();
19     return x*f;
20 }
21 int n,g[MAXN][MAXN],f[MAXN<<2],t[MAXN<<2];
22 int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
23 struct data {int ans[2],m[MAXN<<1];}tr[MAXN<<2];
24 void solve(int k,int p)
25 {
26     tr[k].ans[g[p][1]]=1,tr[k].ans[g[p][1]^1]=0,tr[k].m[1]=tr[k].m[1+n]=1;
27     for(int i=2,j=1;i<=n;i++)
28     {
29         if(g[p][i]!=g[p][j]) tr[k].ans[g[p][i]]++,j=i;
30         tr[k].m[i]=tr[k].m[i+n]=j;
31     }
32 }
33 void upd(int k,int p)
34 {
35     tr[k].ans[0]=tr[k<<1].ans[0]+tr[k<<1|1].ans[0];
36     tr[k].ans[1]=tr[k<<1].ans[1]+tr[k<<1|1].ans[1];
37     //cout<<k<<" "<<p<<endl;
38     for(int i=1;i<=n*2;i++) f[i]=tr[k<<1].m[i];
39     //for(int i=1;i<=n*2;i++) cout<<i<<" "<<f[i]<<" "<<tr[k<<1].m[i]<<endl;
40     for(int i=1;i<=n*2;i++) f[i+n*2]=tr[k<<1|1].m[i]+n*2;
41     //cout<<f[1]<<" "<<f[2]<<endl;
42     for(int i=1;i<=n;i++) if(g[p][i]==g[p+1][i]&&find(i+n)!=find(i+n*2))tr[k].ans[g[p][i]]--,f[f[i+n]]=f[i+n*2];
43     for(int i=1;i<=n*4;i++)
44     {
45         f[i]=find(i);
46         if(i>n*3) t[f[i]]=i-n*2;
47     }
48     for(int i=1;i<=n;i++) tr[k].m[i]=i;
49     for(int i=1;i<=n;i++) tr[k].m[i+n]=t[f[i+n*3]];
50 }
51 void build(int k,int l,int r)
52 {
53     if(l==r) {solve(k,l);return;}
54     int mid=(l+r)>>1;
55     build(k<<1,l,mid),build(k<<1|1,mid+1,r);
56     upd(k,mid);
57 }
58 void mdf(int k,int l,int r,int x)
59 {
60     if(l==r) {solve(k,l);return;}
61     int mid=(l+r)>>1;
62     if(x<=mid) mdf(k<<1,l,mid,x);
63     else mdf(k<<1|1,mid+1,r,x);
64     upd(k,mid);
65 }
66 int main()
67 {
68     n=read();int a,b;
69     for(int i=1;i<=n;i++)
70         for(int j=1;j<=n;j++) g[i][j]=read();
71     build(1,1,n);
72     int T=read();
73     while(T--) a=read(),b=read(),g[a][b]^=1,mdf(1,1,n,a),printf("%d %d\n",tr[1].ans[1],tr[1].ans[0]);
74 }
View Code

 

bzoj 1453 双面棋盘

标签:联通   黑白   har   closed   int   ide   math   names   ==   

原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8419622.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!