题意:
初始有n*m的点,矩形排列。有2种操作,第一种是将第i行的所有点联通(a<=i<=b),第二种是将第i列的所有点联通(a<=i<=b)。每次操作后输出有多少个联通块。
题解:
先说结论,若某次操作后有a行,b列联通,则联通块的个数为n*m-a*(m-1)-b*(n-1)+max(0,(a-1)*b(b-1))。
我们要做的就是维护行和列中联通的个数。
由于行和列的数据范围较大,所以先离散化,在操作。
代码:
#include<bits/stdc++.h>
#define N 100010
#define INF 0x3f3f3f3f
#define eps 1e-10
#define pi 3.141592653589793
#define LL long long
#define pb push_back
#define cl clear
#define si size
#define lb lower_bound
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct node
{
int d,s;
}t[N<<3],tt[N<<3];
int a[N],b[N],op[N],f[N<<1];
void updata(int x,int l,int r,int fl,int fr,node *t)
{
if (l==fl && r==fr)
{
t[x].d=1;
t[x].s=f[r]-f[l];
return;
}
int mid=l+r>>1;
if (t[x].d)
{
t[x<<1].d=1; t[x<<1].s=f[mid]-f[l];
t[x<<1|1].d=1; t[x<<1|1].s=f[r]-f[mid];
t[x].d=0;
}
if (fr<=mid) updata(x<<1,l,mid,fl,fr,t);else
if (fl>=mid) updata(x<<1|1,mid,r,fl,fr,t);else
{
updata(x<<1,l,mid,fl,mid,t);
updata(x<<1|1,mid,r,mid,fr,t);
}
t[x].s=t[x<<1].s+t[x<<1|1].s;
}
int main()
{
int n,m,q;
while(~sccc(n,m,q))
{
memset(t,0,sizeof(node)*(q<<3)); memset(tt,0,sizeof(node)*(q<<3)); int cnt=0;
for (int i=1;i<=q;i++)
{
sccc(op[i],a[i],b[i]);
f[++cnt]=a[i];
f[++cnt]=b[i]+1;
}
f[++cnt]=n+1;
f[++cnt]=m+1;
sort(f+1,f+cnt+1);
cnt=unique(f+1,f+cnt+1)-f-1;
int nn=lb(f+1,f+cnt+1,n+1)-f,mm=lb(f+1,f+cnt+1,m+1)-f;
for (int i=1;i<=q;i++)
{
int x=lower_bound(f+1,f+cnt+1,a[i])-f,y=lower_bound(f+1,f+cnt+1,b[i]+1)-f;
if (op[i]==1) updata(1,1,nn,x,y,t); else updata(1,1,mm,x,y,tt);
printf("%lld\n",(LL)n*m-(LL)t[1].s*(m-1)-(LL)tt[1].s*(n-1)+max(0LL,(LL)(t[1].s-1)*(tt[1].s-1)));
}
}
}