您的位置:首页 > 其它

BZOJ 1018 [SHOI2008]堵塞的交通traffic

2016-03-29 19:26 363 查看
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1018

分析:

  为什么会只有2行呢?...于是我们就想到了:因为如果一行太水了[并查集真的可以弄么?...],如果多行好像又没那么好打了是吧...

  于是想到两行也可以当做一行来玩的吧...和序列有关的,想办法来维护连通性的数据结构...

  于是用到的是线段树咯:

   [下图是一个2*len的区间,其中四个角分别是lu,ru,ld,rd,方便和程序里面的变量对应]

  

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

inline int in(){
int x=0;char ch=getchar();
while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}

const int maxn=100010;
const int max_tree=maxn*5;

struct Node{
bool luru,lurd,ldru,ldrd,luld,rurd;
// lu=left_up,ru=right_up,ld=left_down,rd=right_down;
}s[max_tree];

struct Ans{
bool a,b,c,d,e,f;
}False;

int n,x1,y1,x2,y2;
int num[max_tree];//标记每个节点所代表线段的右端点
bool up[maxn],down[maxn],list[maxn];
//up[i]表示上一行中i往右是否有连边,down[i]表示下一行,list表示上下两行之间

inline void update(int o){
bool a,b;

a=s[o<<1].luru && s[o<<1|1].luru && up[num[o<<1]];
b=s[o<<1].lurd && s[o<<1|1].ldru && down[num[o<<1]];
s[o].luru=a|b;

a=s[o<<1].luru && s[o<<1|1].lurd && up[num[o<<1]];
b=s[o<<1].lurd && s[o<<1|1].ldrd && down[num[o<<1]];
s[o].lurd=a|b;

a=s[o<<1].ldru && s[o<<1|1].luru && up[num[o<<1]];
b=s[o<<1].ldrd && s[o<<1|1].ldru && down[num[o<<1]];
s[o].ldru=a|b;

a=s[o<<1].ldru && s[o<<1|1].lurd && up[num[o<<1]];
b=s[o<<1].ldrd && s[o<<1|1].ldrd && down[num[o<<1]];
s[o].ldrd=a|b;

a=s[o<<1].luld;
b=s[o<<1].luru && s[o<<1].ldrd && s[o<<1|1].luld && up[num[o<<1]] && down[num[o<<1]];
s[o].luld=a|b;

a=s[o<<1|1].rurd;
b=s[o<<1|1].luru && s[o<<1|1].ldrd && s[o<<1].rurd && up[num[o<<1]] && down[num[o<<1]];
s[o].rurd=a|b;
}

void Build(int o,int l,int r){
num[o]=r;
if(l==r){s[o].luru=s[o].ldrd=true;return ;}
int mid=(l+r)>>1;
Build(o<<1,l,mid),Build(o<<1|1,mid+1,r);
update(o);
}

void Modify(int o,int l,int r,int x){
if(l==r){
s[o].luru=s[o].ldrd=true;
s[o].luld=s[o].lurd=s[o].ldru=s[o].rurd=list[l];
return ;
}
int mid=(l+r)>>1;
if(x<=mid) Modify(o<<1,l,mid,x);
else Modify(o<<1|1,mid+1,r,x);
update(o);
}

inline void Change(bool op){
if(x1==x2)
list[x1]=op,Modify(1,1,n,x1);
else{
if(!y1){
up[x1]=op;
Modify(1,1,n,x1);
Modify(1,1,n,x2);
}
else{
down[x1]=op;
Modify(1,1,n,x1);
Modify(1,1,n,x2);
}
}
}

Ans Query(int o,int l,int r,int al,int ar){

if(al<=l && ar>=r)
return (Ans){s[o].luru,s[o].ldrd,s[o].lurd,s[o].ldru,s[o].luld,s[o].rurd};

int mid=(l+r)>>1;
bool pdl=0,pdr=0;
Ans L,R;

if(al<=mid)
pdl=true,L=Query(o<<1,l,mid,al,ar);
if(ar>mid)
pdr=true,R=Query(o<<1|1,mid+1,r,al,ar);

if(pdl && pdr){
bool a,b,c,d,e,f;

a=(L.a && R.a && up[num[o<<1]]) || (L.c && R.d && down[num[o<<1]]);
b=(L.d && R.c && up[num[o<<1]]) || (L.b && R.b && down[num[o<<1]]);
c=(L.a && R.c && up[num[o<<1]]) || (L.c && R.b && down[num[o<<1]]);
d=(L.d && R.a && up[num[o<<1]]) || (L.b && R.d && down[num[o<<1]]);
e=(L.e) || (L.a && L.b && R.e && up[num[o<<1]] && down[num[o<<1]]);
f=(R.f) || (R.a && R.b && L.f && up[num[o<<1]] && down[num[o<<1]]);

return (Ans){a,b,c,d,e,f};
}
else if(pdl) return L;
else if(pdr) return R;
else return False;
}

inline bool ask(){
Ans l,r,m;

m=Query(1,1,n,x1,x2);
l=Query(1,1,n,1,x1);
r=Query(1,1,n,x2,n);

if(!y1 && !y2)
return m.a || (l.f && m.d) || (m.c && r.e) || (l.f && m.b && r.e);
if( y1 &&  y2)
return m.b || (l.f && m.c) || (m.d && r.e) || (l.f && m.a && r.e);
if(!y1 &&  y2)
return m.c || (l.f && m.b) || (m.a && r.e) || (l.f && m.d && r.e);
if( y1 && !y2)
return m.d || (l.f && m.a) || (m.b && r.e) || (l.f && m.c && r.e);
}

int main(){
#ifndef ONLINE_JUDGE
freopen("1018.in","r",stdin);
freopen("1018.out","w",stdout);
#endif

char ord[6];

scanf("%d",&n);
Build(1,1,n);
while(~scanf("%s",ord)){
if(ord[0]=='E') return 0;

y1=in(),x1=in(),y2=in(),x2=in();y1--,y2--;

if(x1>x2){swap(x1,x2);swap(y1,y2);}

if(ord[0]=='O') Change(1);
else if(ord[0]=='C') Change(0);
else{
if(ask()) puts("Y");
else puts("N");
}
}

return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: