http://codeforces.com/gym/101550/attachments
如图所示。
每次染色,然后问你联通块数有多少。
直接看图就行。
思路:比赛的时候想出来了,但是时间不够了,写了一个开头,本来是写对了,但是我看错了坐标,感觉很麻烦就没写。。
离线处理,然后先记录最后一个的联通块数(有一个空块就+1,联通一次就-1.这样就能得到联通块数)然后依次减去以前的操作,再次统计。
错的地方:① 我把他们都变成了一维表,因为我不太会二维并查集并且我感觉那样很慢。。但是有一个地方要注意,下面会画图说。
② 这道题的坐标很魔性。。
绿色这一排,不可以-1,红色这一排不可以+1,(摔啊,直接用一个二维数组存,然后并查的时候用一维不就好了么。用二维的方向坐标就没这么多事了qwq)
#include <bits/stdc++.h>
using namespace std;
/* 暴力维护。
离线处理。
*/
const int maxn=1e6+5000;
struct Node{
int x,y;
int x2,y2;
Node(int a,int b,int c,int d){
x=a;
y=b;
x2=c;
y2=d;
}
};
stack<Node>q;
stack<int>pp;
int num[maxn];
int m,n,q1;
int a,b,c,d;
int fa[maxn];
int cost[4];
int find2(int x){
if(x==fa[x]) return x;
return fa[x]=find2(fa[x]);
}
int ans;
bool merge2(int x,int y){
if(x<0||y<0||x>=m*n||y>=m*n) return false;
int a=find2(x);
int b=find2(y);
if(a==b) return false;
fa[a]=b;
//cout<<"change"<<a<<" "<<b<<"????????"<<x<<" "<<y<<endl;
ans--;
return true;
}
int main()
{ scanf("%d%d%d",&m,&n,&q1);
cost[0]=1;
cost[1]=-1;
cost[2]=n;
cost[3]=-n;
for(int i=0;i<m*n;i++){
fa[i]=i;
}
for(int i=0;i<q1;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
a--,b--,c--,d--;
swap(a,b);swap(c,d);
if(a==c){
if(b>d) swap(b,d);
for(int j=b;j<=d;j++)
num[j*n+a]++;
}
else if(b==d){
if(a>c) swap(a,c);
for(int j=a;j<=c;j++){
num[b*n+j]++;
}
}
q.push(Node(a,b,c,d));
}
ans=0;
for(int i=0;i<m*n;i++){
if(!num[i]){
//cout<<num[i]<<" "<<i<<endl;
ans++;
for(int j=0;j<4;j++){
if(j==0&&(i%n==(n-1))) continue;
if(j==1&&i%n==0) continue;
if(!num[i]&&!num[i+cost[j]])
{ merge2(i,i+cost[j]);
}
}
}
}
//cout<<ans<<"!!"<<endl;
pp.push(ans);
while(!q.empty()){
Node u=q.top();
q.pop();
a=u.x;
b=u.y;
c=u.x2;
d=u.y2;
//cout<<a<<"????"<<b<<c<<d<<endl;
if(a==c){
if(b>d) swap(b,d);
for(int j=b;j<=d;j++){
num[j*n+a]--;
int t=j*n+a;
if(!num[t]) {ans++;
//cout<<t<<"!!!"<<endl;
for(int j=0;j<4;j++){
if(j==0&&t%(n)==(n-1)) continue;
if(j==1&&t%n==0) continue;
if(!num[t]&&!num[t+cost[j]]){
merge2(t,t+cost[j]);
}
}
}
}
}
else if(b==d){
if(a>c) swap(a,c);
for(int j=a;j<=c;j++){
num[b*n+j]--;
int tt=b*n+j;
if(!num[tt]) ans++;
for(int j=0;j<4;j++){
if(j==0&&tt%(n)==(n-1)) continue;
if(j==1&&tt%n==0) continue;
if(!num[tt]&&!num[tt+cost[j]]){
merge2(tt,tt+cost[j]);
}
}
}
}
pp.push(ans);
}
pp.pop();
while(!pp.empty()){
printf("%d\n",pp.top());
pp.pop();
}
return 0;
}