[BZOJ1018]SHOI2008堵塞的交通|线段树
2015-05-13 21:55
183 查看
好神的线段树题,以前只会维护区间什么数值信息的,竟然还可以维护联通性,好题啊,涨姿势了。。
由于只有两行嘛,要保证线段树节点有可加性,我们维护六个信息,分别是右上到右下,右上到左上,右上到左下,右下到左上,右下到左下,左上到左下的联通性,合并的时候自己YY一下,还是很好想的。一点要注意的,父节点的左上到左下不能简单的直接把左儿子的值赋上去,还有可能是左走到右再走回来,右上右下的同理。。然后就是获取答案的时候,不一定就是在[L,R]这个区间里走,有可能会出现像R向右绕一个弯再走过去这样的情况,所以要把[1,L][L,R][R,n]三个区间的联通性都获取。。细节还是很多的。。
由于只有两行嘛,要保证线段树节点有可加性,我们维护六个信息,分别是右上到右下,右上到左上,右上到左下,右下到左上,右下到左下,左上到左下的联通性,合并的时候自己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"); } } }
相关文章推荐
- 【线段树】bzoj1018 [SHOI2008]堵塞的交通traffic
- BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树)
- BZOJ 1018 SHOI2008 堵塞的交通traffic 线段树
- BZOJ_1018_[SHOI2008]_交通堵塞traffic_(线段树)
- [bzoj1018][SHOI2008]堵塞的交通traffic【线段树】
- [BZOJ1018][SHOI2008]堵塞的交通traffic(线段树)
- [BZOJ1018][SHOI2008]堵塞的交通traffic(线段树)
- BZOJ1018 SHOI2008堵塞的交通(线段树)
- bzoj1018: [SHOI2008]堵塞的交通traffic 线段树区间合并
- BZOJ 1018|SHOI 2008|堵塞的交通|线段树
- BZOJ[1018][SHOI2008]堵塞的交通traffic 线段树
- 数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic
- BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]
- [BZOJ1018][SHOI2008]堵塞的交通traffic(线段树维护连通性)
- 【BZOJ1018】【SHOI2008】堵塞的交通traffic(线段树)(好题)
- bzoj 1018: [SHOI2008]堵塞的交通traffic (线段树维护连通性)
- BZOJ.1018.[SHOI2008]堵塞的交通(线段树维护连通性)
- [bzoj1018][SHOI2008]堵塞的交通traffic——线段树
- 【BZOJ1018】[SHOI2008]堵塞的交通traffic 线段树
- 【bzoj1018】[SHOI2008]堵塞的交通traffic 线段树维护连通性