bzoj1018 [SHOI2008]堵塞的交通traffic——线段树
Posted zinn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1018 [SHOI2008]堵塞的交通traffic——线段树相关的知识,希望对你有一定的参考价值。
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1018
线段树竟然还可以这样用!
维护的是一个矩形内部的连通情况,四个顶点之间有6中连通方式;
因为连通情况具有可合并性,所以可以用线段树来维护!
这篇博客写得很好:https://www.cnblogs.com/DUXT/p/6029815.html
茅塞顿开之后看到这篇博客,觉得写得很好呢:https://www.cnblogs.com/MashiroSky/p/5973686.html
我就是模仿上面第二篇博客写的,感觉自己对线段树的认识又加深了。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=100005; int c,r1,r2,c1,c2; char ch[10]; struct N{int U,D,u,d,l,r,p,q;}w[maxn<<2]; struct T{int l,r;}tr[maxn<<2]; void merge(N &k,N x,N y)//& { k.l=x.l|(x.u & k.U & y.l & k.D &x.d); k.r=y.r|(y.u & k.U & x.r & k.D & y.d); k.u=(x.u & k.U & y.u)|(x.q & k.D & y.p); k.d=(x.d & k.D & y.d)|(x.p & k.U & y.q); k.p=(x.d & k.D & y.p)|(x.p & k.U & y.u); k.q=(x.u & k.U & y.q)|(x.q & k.D & y.d); } void build(int k,int l,int r) { tr[k].l=l; tr[k].r=r; if(l==r){w[k].U=w[k].D=w[k].u=w[k].d=1;return;} int mid=((l+r)>>1); build(k<<1,l,mid); build(k<<1|1,mid+1,r); // merge(w[k],w[k<<1],w[k<<1|1]);//初始全不连通 } void updater(int k,int T,int x,int val)//同一行 { int l=tr[k].l,r=tr[k].r,mid=((l+r)>>1); if(x==mid) { if(T==1) w[k].U=val; else w[k].D=val; merge(w[k],w[k<<1],w[k<<1|1]); return; } if(x<=mid) updater(k<<1,T,x,val); else updater(k<<1|1,T,x,val); merge(w[k],w[k<<1],w[k<<1|1]); } void updatec(int k,int x,int val)//同一列 { int l=tr[k].l,r=tr[k].r,mid=((l+r)>>1); if(l==r){w[k].l=w[k].r=w[k].p=w[k].q=val;return;} if(x<=mid) updatec(k<<1,x,val); else updatec(k<<1|1,x,val); merge(w[k],w[k<<1],w[k<<1|1]); } N query(int k,int l,int r) { int s=tr[k].l,t=tr[k].r,mid=((s+t)>>1); if(s>=l&&t<=r) return w[k]; if(r<=mid) return query(k<<1,l,r); else if(l>mid) return query(k<<1|1,l,r); else { N ret=w[k];//保留 U,D merge(ret,query(k<<1,l,r),query(k<<1|1,l,r)); return ret; } } int main() { scanf("%d",&c); build(1,1,c); while(1) { scanf("%s",&ch); if(ch[0]==‘E‘)return 0; scanf("%d%d%d%d",&r1,&c1,&r2,&c2); if(c1>c2) swap(c1,c2),swap(r1,r2); if(ch[0]==‘O‘) { if(r1==r2)updater(1,r1,c1,1); else updatec(1,c1,1); } if(ch[0]==‘C‘) { if(r1==r2)updater(1,r1,c1,0); else updatec(1,c1,0); } if(ch[0]==‘A‘) { N l=query(1,1,c1),x=query(1,c1,c2),r=query(1,c2,c); int ans=0; if(r1==1&&r2==1) ans=x.u|(l.r & x.d & r.l)|(x.q & r.l)|(l.r & x.p); if(r1==1&&r2==2) ans=x.q|(l.r & x.p & r.l)|(l.r & x.d)|(x.u & r.l); if(r1==2&&r2==1) ans=x.p|(l.r & x.q & r.l)|(l.r & x.u)|(x.d & r.l); if(r1==2&&r2==2) ans=x.d|(l.r & x.u & r.l)|(x.p & r.l)|(l.r & x.q); if(ans) printf("Y "); else printf("N "); } } }
以上是关于bzoj1018 [SHOI2008]堵塞的交通traffic——线段树的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1018: [SHOI2008]堵塞的交通traffic
BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]
BZOJ1018: [SHOI2008]堵塞的交通traffic