[SHOI2008]堵塞的交通
链接
题解
线段树之什么都能维护
用线段树维护连通性。
用线段树维护一个区间的连通性,发现你其实需要维护的本质不同的信息就是这个矩形上下左右以及两条对角线的连通性。
然后考虑合并两个矩形连通性,发现因为矩形高度只有 \(2\),所以可以帮你排除一些感觉很奇怪的合并方法,具体可以看这篇的图很清晰。
修改时,对于竖边直接传到 l=r 修改;对于横边,修改影响最小的区间是以这条横边为 mid 的区间。
最后统计答案时要分成三块来考虑,根据所有可能路径的组成来合并。
总之是一道比较大力分类讨论加牛逼线段树的题。
code
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define in read()
inline int read(){
int p=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){p=p*10+c-48;c=getchar();}
return p*f;
}
cs int N=1e5+5;
int n;
bool uc[N],dc[N];
struct node{
int l,r,u,d,lu,ru;
int L,R;
}a[N<<2];
inline void pushup(node &p,node x,node y){
p.L=x.L,p.R=y.R;int mid=x.R;
p.l=x.l|(x.u&x.d&uc[mid]&dc[mid]&y.l);
p.r=y.r|(y.u&y.d&uc[mid]&dc[mid]&x.r);
p.u=(x.u&uc[mid]&y.u)|(x.lu&dc[mid]&y.ru);
p.d=(x.d&dc[mid]&y.d)|(x.ru&uc[mid]&y.lu);
p.lu=(x.lu&dc[mid]&y.d)|(x.u&uc[mid]&y.lu);
p.ru=(x.ru&uc[mid]&y.u)|(x.d&dc[mid]&y.ru);
}
inline void built(int l,int r,int p){
if(l==r){a[p].l=a[p].r=a[p].lu=a[p].ru=0,a[p].u=a[p].d=1,a[p].L=a[p].R=l;return ;}
int mid=(l+r)>>1;built(l,mid,p<<1),built(mid+1,r,p<<1|1),pushup(a[p],a[p<<1],a[p<<1|1]);
}
inline void change1(int l,int r,int p,int x,int d){
int mid=(l+r)>>1;
if(l==r){a[p].l=a[p].r=a[p].lu=a[p].ru=d;return ;}
if(x<=mid)change1(l,mid,p<<1,x,d);
else change1(mid+1,r,p<<1|1,x,d);
pushup(a[p],a[p<<1],a[p<<1|1]);
}
inline void change2(int l,int r,int p,int x,int ud,int d){
int mid=(l+r)>>1;
if(mid==x){
if(ud)uc[x]=d;
else dc[x]=d;
pushup(a[p],a[p<<1],a[p<<1|1]);
return ;
}
if(x<mid)change2(l,mid,p<<1,x,ud,d);
else change2(mid+1,r,p<<1|1,x,ud,d);
pushup(a[p],a[p<<1],a[p<<1|1]);
}
inline node query(int l,int r,int p,int ql,int qr){
if(l>=ql&&r<=qr)return a[p];
int mid=(l+r)>>1;
if(qr<=mid)return query(l,mid,p<<1,ql,qr);
if(ql>mid)return query(mid+1,r,p<<1|1,ql,qr);
node ans;pushup(ans,query(l,mid,p<<1,ql,qr),query(mid+1,r,p<<1|1,ql,qr));
return ans;
}
string s;
int r1,c1,r2,c2;
int T=0;
signed main(){
n=in,built(1,n,1),cin>>s;
while(s[0]!='E'){
r1=in,c1=in,r2=in,c2=in;
if(c1>c2)swap(r1,r2),swap(c1,c2);
if(s[0]=='A'){
bool ans;
node ans1=query(1,n,1,1,c1),ans2=query(1,n,1,c1,c2),ans3=query(1,n,1,c2,n);
if(c1==c2) ans=ans1.r|ans2.l|ans3.l;
else if(r1==1&&r2==1) ans=ans2.u|(ans1.r&ans2.ru)|(ans2.lu&ans3.l)|(ans1.r&ans2.d&ans3.l);
else if(r1==2&&r2==2) ans=ans2.d|(ans1.r&ans2.lu)|(ans2.ru&ans3.l)|(ans1.r&ans2.u&ans3.l);
else if(r1==1&&r2==2) ans=ans2.lu|(ans1.r&ans2.d)|(ans2.u&ans3.l)|(ans1.r&ans2.ru&ans3.l);
else ans=ans2.ru|(ans1.r&ans2.u)|(ans2.d&ans3.l)|(ans1.r&ans2.lu&ans3.l);
if(ans)cout<<"Y\n";
else cout<<"N\n";
}
else{
if(r1^r2)change1(1,n,1,c1,s[0]=='O');
else change2(1,n,1,c1,r1==1,s[0]=='O');
}
cin>>s;
}
return 0;
}