BZOJ1453: [WC2005]Dface双面棋盘

离线LCT维护MST,和3082的方法一样。然而比较码农,适合颓废的时候写。

PS:线段树分治要好写得多,LCT比较自娱自乐。

#include<bits/stdc++.h>
using namespace std;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
const int inf=1e9;
int n;
int cal1(int x1,int y1,int x2,int y2){
	int i=(min(x1,x2)*n+min(y1,y2))*2;
	return x1==x2?i:i+1;
}
struct node;
typedef node*ptr;
struct vec{
	int v;ptr i,s,t;
	vec(){v=inf;}
};
bool operator<(vec a,vec b){
	return a.v<b.v;
}
struct node{
	ptr i,j,p;bool r;vec v,s;
	node();
	ptr up(){
		s=min(min(v,i->s),j->s);
		return this;
	}
	void down(){
		if(r)
			i->r^=1,j->r^=1,swap(i,j),r=0;
	}
}e[120000];
node::node(){i=j=p=e;}
bool root(ptr o){
	return o!=o->p->i&&o!=o->p->j;
}
void turn(ptr o){
	ptr s=o->p,t=s->p;
	if(!root(s))(s==t->i?t->i:t->j)=o;
	o->p=t,s->p=o;
	if(o==s->i)
		s->i=o->j,o->j->p=s,o->j=s->up();
	else
		s->j=o->i,o->i->p=s,o->i=s->up();
}
void push(ptr o){
	if(!root(o))push(o->p);
	o->down();
}
ptr splay(ptr o){
	push(o);
	while(!root(o)){
		if(!root(o->p))turn(o==o->p->i^o->p==o->p->p->i?o:o->p);
		turn(o);
	}
	return o->up();
}
ptr exp(ptr o){
	ptr s=e;
	while(o!=e)splay(o)->j=s,s=o->up(),o=o->p;
	return s;
}
ptr bel(ptr o){
	o=exp(o);
	while(o->i!=e)o=o->i,o->down();
	return o;
}
bool jud(ptr s,ptr t){
	exp(s)->r=1;
	return bel(t)==s;
}
void link(ptr s,ptr t){
	exp(s)->r=1,splay(s)->p=t;
}
bool cut(ptr s,ptr t){
	exp(s)->r=1,exp(t);
	splay(t);
	if(s==t->i&&s->j==e)
		return t->i=s->p=e;
	return 0;
}
ptr cal2(int i){
	return e+n*n+i+1;
}
bool link(int x1,int y1,int x2,int y2){
	ptr s=e+x1*n+y1+1;
	ptr t=e+x2*n+y2+1;
	int i=cal1(x1,y1,x2,y2);
	if(!jud(s,t)){
		link(s,cal2(i));
		link(t,cal2(i));
		return 1;
	}
	exp(s)->r=1;
	vec v=exp(t)->s;
	if(v<cal2(i)->v){
		cut(v.s,v.i);
		cut(v.t,v.i);
		link(s,cal2(i));
		link(t,cal2(i));
	}
	return 0;
}
bool cut(int x1,int y1,int x2,int y2){
	ptr s=e+x1*n+y1+1;
	ptr t=e+x2*n+y2+1;
	int i=cal1(x1,y1,x2,y2);
	if(cut(s,cal2(i)))
		return cut(t,cal2(i));
	return 0;
}
int m,t,c6[2],c1[200][200];
queue<int>c3[80000];
void pre(int x1,int y1,int x2,int y2){
	if(!~x1||x1==n||!~y1||y1==n||!~x2||x2==n||!~y2||y2==n)
		return;
	int i=cal1(x1,y1,x2,y2);
	if(c1[x1][y1]==c1[x2][y2])
		c3[i].push(t);
}
void ins(int x1,int y1,int x2,int y2){
	if(!~x1||x1==n||!~y1||y1==n||!~x2||x2==n||!~y2||y2==n)
		return;
	int i=cal1(x1,y1,x2,y2);
	if(c1[x1][y1]==c1[x2][y2]){
		cal2(i)->v.i=cal2(i);
		cal2(i)->v.s=e+x1*n+y1+1;
		cal2(i)->v.t=e+x2*n+y2+1;
		if(c3[i].empty())
			cal2(i)->v.v=inf;
		else{
			cal2(i)->v.v=c3[i].front();
			c3[i].pop();
		}
		if(link(x1,y1,x2,y2))
			--c6[c1[x1][y1]];
	}
}
void del(int x1,int y1,int x2,int y2){
	if(0<=x1&&x1<n&&0<=y1&&y1<n&&0<=x2&&x2<n&&0<=y2&&y2<n&&c1[x1][y1]==c1[x2][y2]&&cut(x1,y1,x2,y2))
		++c6[c1[x1][y1]];
}
struct que{int x,y;};
que c2[10000];
int main(){
	struct{
		operator int(){
			int x=0,c=getchar();
			while(c<48)c=getchar();
			while(c>32)
				x=x*10+c-48,c=getchar();
			return x;
		}
	}it;
	n=it;
	for(int i=0;i<n;++i)
		for(int j=0;j<n;++j)
			++c6[c1[i][j]=it];
	m=it;
	for(int&i=t=0;i<m;++i){
		int x=it-1,y=it-1;
		c2[i].x=x,c2[i].y=y;
		for(int j=0;j<4;++j)
			pre(x,y,x+dx[j],y+dy[j]);
		c1[x][y]^=1;
	}
	for(int i=m-1;~i;--i)
		c1[c2[i].x][c2[i].y]^=1;
	for(int i=0;i<n;++i)
		for(int j=0;j<n;++j){
			ins(i,j,i,j+1);
			ins(i,j,i+1,j);
		}
	for(int i=0;i<m;++i){
		int x=c2[i].x,y=c2[i].y;
		for(int j=0;j<4;++j)
			del(x,y,x+dx[j],y+dy[j]);
		--c6[c1[x][y]];
		++c6[c1[x][y]^=1];
		for(int j=0;j<4;++j)
			ins(x,y,x+dx[j],y+dy[j]);
		printf("%d %d\n",c6[1],c6[0]);
	}
}
posted @ 2017-03-13 21:42  f321dd  阅读(169)  评论(0编辑  收藏  举报