2018 HNCPC 湖南省程式設計競賽 CSU 2167 Grid
阿新 • • 發佈:2018-12-09
題意:
初始有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))); } } }