题意:

初始有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)));
        }
    }
}