您的位置:首页 > 其它

[BZOJ1018]SHOI2008堵塞的交通|线段树

2015-05-13 21:55 183 查看
好神的线段树题,以前只会维护区间什么数值信息的,竟然还可以维护联通性,好题啊,涨姿势了。。

由于只有两行嘛,要保证线段树节点有可加性,我们维护六个信息,分别是右上到右下,右上到左上,右上到左下,右下到左上,右下到左下,左上到左下的联通性,合并的时候自己YY一下,还是很好想的。一点要注意的,父节点的左上到左下不能简单的直接把左儿子的值赋上去,还有可能是左走到右再走回来,右上右下的同理。。然后就是获取答案的时候,不一定就是在[L,R]这个区间里走,有可能会出现像R向右绕一个弯再走过去这样的情况,所以要把[1,L][L,R][R,n]三个区间的联通性都获取。。细节还是很多的。。

#include<cstdio>
#include<iostream>
#include<memory.h>
#define lc x*2
#define rc x*2+1
#define N 400405
using namespace std;
int n,x1,y1,x2,y2,qd,ans,ansl,ansr;
bool l12
,r12
,lr1
,lr2
,l1r2
,l2r1
,a
[2][2];//a数组0向下1向右
char s[10];
void build(int x,int l,int r)
{
if (l==r)
{
lr1[x]=lr2[x]=true;
return;
}
build(lc,l,(l+r)>>1);build(rc,(l+r)/2+1,r);
}
void update(int x,int mid,int lcc,int rcc)
{
l12[x]=l12[lcc]||(lr1[lcc]&&a[mid][0][1]&&l12[rcc]&&a[mid][1][1]&&lr2[lcc]);
r12[x]=r12[rcc]||(lr1[rcc]&&a[mid][0][1]&&r12[lcc]&&a[mid][1][1]&&lr2[rcc]);
lr1[x]=(lr1[lcc]&&a[mid][0][1]&&lr1[rcc])||(l1r2[lcc]&&a[mid][1][1]&&l2r1[rcc]);
lr2[x]=(lr2[lcc]&&a[mid][1][1]&&lr2[rcc])||(l2r1[lcc]&&a[mid][0][1]&&l1r2[rcc]);
l1r2[x]=(lr1[lcc]&&a[mid][0][1]&&l1r2[rcc])||(l1r2[lcc]&&a[mid][1][1]&&lr2[rcc]);
l2r1[x]=(lr2[lcc]&&a[mid][1][1]&&l2r1[rcc])||(l2r1[lcc]&&a[mid][0][1]&&lr1[rcc]);
}
void change(int x,int l,int r,int x1,int y1,int x2,int y2,bool k)
{
int mid=(l+r)/2;
if (y1==y2)
{
if (l==r)
{
a[y1][0][0]=k;
l12[x]=r12[x]=l1r2[x]=l2r1[x]=k;
return;
}
if (y1<=mid) change(lc,l,mid,x1,y1,x2,y2,k);else change(rc,mid+1,r,x1,y1,x2,y2,k);
update(x,mid,lc,rc);
}
else
{
a[y1][x1][1]=k;
if (mid==y1&&mid+1==y2) update(x,mid,lc,rc);
else
{
if (mid>=y2) change(lc,l,mid,x1,y1,x2,y2,k);else change(rc,mid+1,r,x1,y1,x2,y2,k);
update(x,mid,lc,rc);
}
}
}
int query(int x,int l,int r,int y1,int y2)
{
if (y1<=l&&y2>=r) return x;
int mid=(l+r)>>1;
if (y2<=mid) return query(lc,l,mid,y1,y2);
else if (y1>mid) return query(rc,mid+1,r,y1,y2);
else
{
int ans=++qd,lcc=query(lc,l,mid,y1,mid),rcc=query(rc,mid+1,r,mid+1,y2);
update(ans,mid,lcc,rcc);
return ans;
}
}
int main()
{
freopen("1018.in","r",stdin);
//	freopen("1018.out","w",stdout);
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(l12,0,sizeof(l12));memset(r12,0,sizeof(r12));
memset(lr1,0,sizeof(lr1));memset(lr2,0,sizeof(lr2));
memset(l2r1,0,sizeof(l2r1));memset(l1r2,0,sizeof(l1r2));
build(1,1,n);
int t=1;
while (t++)
{
scanf("%s",&s);
if (s[0]=='E') return 0;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if (y1>y2) swap(y1,y2),swap(x1,x2);
x1--;x2--;
if (s[0]=='O') change(1,1,n,x1,y1,x2,y2,true);
else if (s[0]=='C') change(1,1,n,x1,y1,x2,y2,false);
else
{
qd=400000;
ans=query(1,1,n,y1,y2);ansl=query(1,1,n,1,y1);ansr=query(1,1,n,y2,n);
if ((x1==0&&x2==0&&(lr1[ans]||(r12[ansl]&&l2r1[ans])||(l12[ansr]&&l1r2[ans])||(r12[ansl]&&l12[ansr]&&lr2[ans])))||(x1==1&&x2==1&&(lr2[ans]||(r12[ansl]&&l1r2[ans])||(l12[ansr]&&l2r1[ans])||(r12[ansl]&&l12[ansr]&&lr1[ans])))||(x1==0&&x2==1&&(l1r2[ans]||(r12[ansl]&&lr2[ans])||(l12[ansr]&&lr1[ans])))||(x1==1&&x2==0&&(l2r1[ans]||(r12[ansl]&&lr1[ans])||(l12[ansr]&&lr2[ans])))) printf("Y\n");
else printf("N\n");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: