标签:
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1018
用线段树维护区间连通性,对于每一个区间记录6个域表示(左上,左下)(左上,右上)(右上,右下)(左下,右下)(左上,右下)(左下,右上)的连通情况。
因为是与相邻点的关系所以维护一个数组表示当前列x与列x+1的连边情况和当前列x的第一行与第二行的连边情况。
然后就是区间合并。。各种分类讨论。。
#include<cstring> #include<iostream> #include<algorithm> #include<cstdio> #include<queue> #include<map> #include<vector> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define ll long long #define maxn 100500 #define mm 998244353 using namespace std; struct data{int b[6],l,r; }t[maxn*4]; int road[maxn][3],n; char s[10]; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)){if (ch==‘-‘) f=-1; ch=getchar();} while (isdigit(ch)){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } data M(data l,data r){ data i; i.l=l.l; i.r=r.r; i.b[0]=(l.b[0])||( ( (l.b[1]&&l.b[3]) || (l.b[4]&&l.b[5]) )&&(road[l.r][0])&&(road[l.r][1])&&(r.b[0])); i.b[2]=(r.b[2])||( ( (r.b[1]&&r.b[3]) || (r.b[4]&&r.b[5]) )&&(road[l.r][0])&&(road[l.r][1])&&(l.b[2])); i.b[1]=(l.b[1]&&r.b[1]&&road[l.r][0]) || (l.b[4]&&r.b[5]&&road[l.r][1]); i.b[3]=(l.b[3]&&r.b[3]&&road[l.r][1]) || (l.b[5]&&r.b[4]&&road[l.r][0]); i.b[4]=(l.b[1]&&r.b[4]&&road[l.r][0]) || (l.b[4]&&r.b[3]&&road[l.r][1]); i.b[5]=(l.b[5]&&r.b[1]&&road[l.r][0]) || (l.b[3]&&r.b[5]&&road[l.r][1]); return i; } void build(int i,int l,int r){ t[i].l=l; t[i].r=r; int mid=(l+r)/2; if (l==r){ t[i].b[1]=t[i].b[3]=1; return; } build(i*2,l,mid); build(i*2+1,mid+1,r); t[i]=M(t[i*2],t[i*2+1]); } void change(int pos,int i){ int l=t[i].l,r=t[i].r,mid=(l+r)/2; if (l==r){ rep(j,0,5) t[i].b[j]=road[l][2]; t[i].b[1]=t[i].b[3]=1; return; } if (pos<=mid) change(pos,i*2); else change(pos,i*2+1); t[i]=M(t[i*2],t[i*2+1]); } void change(int x0,int y0,int x1,int y1,int flag){ if (y0>y1) swap(x0,x1),swap(y0,y1); if (x0==x1) { if (x0==1) road[y0][0]=flag; else road[y0][1]=flag; } else road[y0][2]=flag; change(y0,1); } data ask(int i,int tl,int tr){ int l=t[i].l,r=t[i].r,mid=(l+r)/2; if (l==tl&&r==tr) return t[i]; if (tr<=mid) return ask(i*2,tl,tr); else if (tl>mid) return ask(i*2+1,tl,tr); else return M(ask(i*2,tl,mid),ask(i*2+1,mid+1,tr)); } bool query(int x0,int y0,int x1,int y1){ if (y0>y1) swap(x0,x1),swap(y0,y1); data x=ask(1,1,y0),y=ask(1,y0,y1),z=ask(1,y1,n); if (x0==x1) { if (x0==1){ if (y.b[1]) return 1; if ((x.b[2]||y.b[0])&&(y.b[2]||z.b[0])&&y.b[3]) return 1; if ((y.b[4])&&(y.b[2]||z.b[0])) return 1; if ((y.b[5])&&(x.b[2]||y.b[0])) return 1; return 0; } else { if (y.b[3]) return 1; if ((x.b[2]||y.b[0])&&(y.b[2]||z.b[0])&&y.b[1]) return 1; if ((y.b[5])&&(y.b[2]||z.b[0])) return 1; if ((y.b[4])&&(x.b[2]||y.b[0])) return 1; return 0; } } else { if (x0==1){ if (y.b[4]) return 1; if ((x.b[2]||y.b[0])&&y.b[3]) return 1; if ((x.b[2]||y.b[0])&&(y.b[2]||z.b[0])&&y.b[5]) return 1; if ((y.b[2]||z.b[0])&&y.b[1]) return 1; return 0; } else { if (y.b[5]) return 1; if ((x.b[2]||y.b[0])&&y.b[1]) return 1; if ((x.b[2]||y.b[0])&&(y.b[2]||z.b[0])&&y.b[4]) return 1; if ((y.b[2]||z.b[0])&&y.b[3]) return 1; return 0; } } } int main(){ n=read(); build(1,1,n); int x0,x1,y0,y1; while (1){ scanf("%s",s); if (s[0]==‘E‘) break; x0=read(); y0=read(); x1=read(); y1=read(); if (s[0]==‘O‘) change(x0,y0,x1,y1,1); else if (s[0]==‘C‘) change(x0,y0,x1,y1,0); else printf("%c\n",query(x0,y0,x1,y1)?‘Y‘:‘N‘); } return 0; }
BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树)
标签:
原文地址:http://www.cnblogs.com/ctlchild/p/5094813.html