您的位置:首页 > 其它

bzoj1018 [SHOI2008]堵塞的交通traffic

2017-09-09 15:35 357 查看
传送门

恶心的线段树。。。

吐槽:这题update真tm难写……

线段树维护连通性以前听说过,但这一次是第一次写,结果写吐了。。

由于城市中道路是2行n列,所以我们可以在线段树中维护左边两个点和右边两个点以及左边两个点之间和右边两个点之间的连通性。横着的操作可以在线段树递归到这条边连接左右子树的时候进行操作,竖着的操作可以在递归到叶子的时候将一对点看作两对点,然后将其位于对角线上的两对点以及左边一对和右边一对的连通性修改,其余的注意update就行了。

CODE:

#include<cstdio>
#define N 100005
struct tree
{
bool a[2][2];
bool left,right;
bool up,down;
}t[N<<2];
char str[10];
int n,x1,y1,x2,y2;
inline void swap(int &a,int &b){a^=b,b^=a,a^=b;}
inline bool getstring()
{
char c=getchar();int p=0;
while((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();
while((c>='A'&&c<='Z')||(c>='a'&&c<='z')) str[++p]=c,c=getchar();
return str[1]!='E';
}
inline void update(tree &now,tree &s1,tree &s2)
{
now.a[0][0]=(s1.a[0][0]&&now.up&&s2.a[0][0])||(s1.a[0][1]&&now.down&&s2.a[1][0]);
now.a[0][1]=(s1.a[0][0]&&now.up&&s2.a[0][1])||(s1.a[0][1]&&now.down&&s2.a[1][1]);
now.a[1][0]=(s1.a[1][0]&&now.up&&s2.a[0][0])||(s1.a[1][1]&&now.down&&s2.a[1][0]);
now.a[1][1]=(s1.a[1][0]&&now.up&&s2.a[0][1])||(s1.a[1][1]&&now.down&&s2.a[1][1]);
now.left =s1.left ||(s1.a[0][0]&&s1.right&&s1.a[1][1])||(s1.a[0][0]&&now.up&&s2.left &&now.down&&s1.a[1][1])||(s1.a[0][0]&&now.up&&s2.a[0][0]&&s2.right&&s2.a[1][1]&&now.down&&s1.a[1][1]);
now.right=s2.right||(s2.a[0][0]&&s2.left &&s2.a[1][1])||(s2.a[0][0]&&now.up&&s1.right&&now.down&&s2.a[1][1])||(s2.a[0][0]&&now.up&&s1.a[0][0]&&s1.left &&s1.a[1][1]&&now.down&&s2.a[1][1]);
}
void build(int l,int r,int now)
{
if(l==r)
{
t[now].a[0][0]=t[now].a[1][1]=1;
return;
}
int mid=(l+r)>>1;
build(l,mid,now<<1);
build(mid+1,r,now<<1|1);
}
void add1(int l,int r,int now,bool change)
{
int mid=(l+r)>>1;
if(y1==mid)
{
if(x1==1) t[now].up=change;
else t[now].down=change;
update(t[now],t[now<<1],t[now<<1|1]);
return;
}
if(y1<mid) add1(l,mid,now<<1,change);
else add1(mid+1,r,now<<1|1,change);
update(t[now],t[now<<1],t[now<<1|1]);
}
void add2(int l,int r,int now,bool change)
{
if(l==r)
{
t[now].a[0][1]=t[now].a[1][0]=change;
t[now].left=t[now].right=change;
return;
}
int mid=(l+r)>>1;
if(y1<=mid) add2(l,mid,now<<1,change);
else add2(mid+1,r,now<<1|1,change);
update(t[now],t[now<<1],t[now<<1|1]);
}
tree ask(int L,int R,int l,int r,int now)
{
if(L>R||L<0||R>n) return t[0];
if(L<=l&&r<=R) return t[now];
int mid=(l+r)>>1;
if(R<=mid) return ask(L,R,l,mid,now<<1);
if(L>mid) return ask(L,R,mid+1,r,now<<1|1);
tree ans=t[now],tmp1,tmp2;
tmp1=ask(L,R,l,mid,now<<1);
tmp2=ask(L,R,mid+1,r,now<<1|1);
update(ans,tmp1,tmp2);
return ans;
}
inline void change(bool wh)
{
if(x1==x2)
{
if(y1>y2) swap(y1,y2);
return add1(1,n,1,wh);
}
if(x1>x2) swap(x1,x2);
add2(1,n,1,wh);
}
inline bool Ask()
{
if(y1>y2) swap(x1,x2),swap(y1,y2);
tree mid=ask(y1,y2,1,n,1);
int wh1=x1==1?0:1,wh2=x2==1?0:1;
if(mid.a[wh1][wh2]) return 1;
tree left=ask(1,y1-1,1,n,1),right=ask(y2+1,n,1,n,1);
tree llink=ask(y1-1,y1,1,n,1),rlink=ask(y2,y2+1,1,n,1);
if(!mid.left) mid.left=(llink.a[0][0]&&llink.a[1][1]&&left.right);
if(!mid.right) mid.right=(rlink.a[0][0]&&rlink.a[1][1]&&right.left);
if(!wh1&&!wh2) return mid.a[0][0]||(mid.left&&mid.a[1][1]&&mid.right);
if(!wh1&&wh2) return (mid.a[0][0]&&mid.right)||(mid.left&&mid.a[1][1]);
if(wh1&&!wh2) return (mid.left&&mid.a[0][0])||(mid.a[1][1]&&mid.right);
return mid.a[1][1]||(mid.left&&mid.a[0][0]&&mid.right);
}
int main()
{
scanf("%d",&n);
build(1,n,1);
while(getstring())
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(str[1]=='O') change(1);
else if(str[1]=='C') change(0);
else if(Ask()) puts("Y");
else puts("N");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息