Can Nowcodercontest5278 J arrive?

Can Nowcodercontest5278 J arrive?

Analysis: Violence and collecting statistical connectivity blocks, but divide the graph into \ (O (k) \) neat rectangles, and then consider the adjacent ones to merge

Separate rectangles:

For each black dot , it is sorted in an increasing order of \ ((x, y) \) , and each line with black dots is divided into \ (k + 1 \) segment rectangles, and the line width is 1

If there is no black dot, find the blank area furthest on both sides \ (x1, x2 \) , the column width is \ (m \)

Merge rectangles:

After getting \ (O (k) \) rectangles, you can see that the rectangle's \ (x1, x2 \) are aligned and divided into several segments. For each adjacent \ (x1, x2 \) , \ (x3 , x4 \) , merge all adjacent \ (y \) , you can find the neighbors, and check the set merge

The total complexity is \ (O (k \ log k + k \ cdot \ alpha (k)) \)

const int N=3e6+10,P=1e9+7;

int n,m,k;
struct Point{//黑点
	int x,y;
	bool operator < (const Point __) const {
		return x<__.x || (x==__.x && y<__.y);
	}
}A[N];

struct Rec{// 矩形
	int lx,rx,ly,ry;
}B[N];
int cnt;
int fa[N];
ll sz[N];
int Find(int x){ return fa[x]==x?x:fa[x]=Find(fa[x]); }
void Union(int x,int y) {
	x=Find(x),y=Find(y);
	if(x==y) return;
	sz[x]+=sz[y],fa[y]=x;
}

int L[N],R[N],fc;

int Check(Rec a,Rec b){
	if(a.ly>b.ly) swap(a,b);
	return a.ry>=b.ly;
} // 检测是否相交


int main() {
	rep(kase,1,rd()) {
		n=rd(),m=rd(),k=rd();
		if(!k) {
			ll ans=1ll*n*m%P;
			ans=(ans*(ans-1)/2+ans)%P;
			printf("%lld\n",ans);
			continue;
		}
		rep(i,1,k) A[i].x=rd(),A[i].y=rd();
		sort(A+1,A+k+1),cnt=0;
		if(A[1].x>1) B[++cnt]=(Rec){1,A[1].x-1,1,m};
		rep(i,1,k) {
			int j=i;
			while(j<k && A[j+1].x==A[j].x) ++j;
			if(A[i].y>1) B[++cnt]=(Rec){A[i].x,A[i].x,1,A[i].y-1};
			rep(d,i+1,j) if(A[d].y-1>A[d-1].y+1) B[++cnt]=(Rec){A[i].x,A[i].x,A[d-1].y+1,A[d].y-1};
			if(A[j].y<m) B[++cnt]=(Rec){A[i].x,A[i].x,A[j].y+1,m}; // 切成k+1段
			i=j;
			if(i<k && A[i+1].x>A[i].x+1) B[++cnt]=(Rec){A[i].x+1,A[i+1].x-1,1,m};// 没有出现黑点的位置
		}
		if(A[k].x<n) B[++cnt]=(Rec){A[k].x+1,n,1,m};// 没有

		rep(i,1,cnt) sz[i]=1ll*(B[i].rx-B[i].lx+1)*(B[i].ry-B[i].ly+1),fa[i]=i; // 预处理并查集

		fc=0;
		rep(i,1,cnt) {
			int j=i;
			while(j<cnt && B[j+1].lx==B[j].lx && B[j+1].rx==B[j].rx) ++j;
			L[++fc]=i,R[fc]=j;
			i=j;
		}//每一层的x1,x2切开
		rep(i,1,fc-1) {
			if(B[i].rx<B[i+1].lx-1) continue;
			int p=L[i];
			rep(j,L[i+1],R[i+1]) {
				while(p<R[i] && B[p+1].ry<=B[j].ry) {
					if(Check(B[j],B[p])) Union(j,p);
					++p;
				}
				if(Check(B[j],B[p])) Union(j,p);
				if(p<R[i] && Check(B[j],B[p+1])) Union(j,p+1);
			}
		}//相邻层合并,p是尺取指针
		ll ans=0;
		rep(i,1,cnt) if(Find(i)==i) {
			sz[i]%=P;
			ans=(ans+sz[i]*(sz[i]-1)/2+sz[i])%P;
		}
		ans=(ans%P+P)%P;
		printf("%lld\n",ans);
	}
}


Guess you like

Origin www.cnblogs.com/chasedeath/p/12727428.html