[SHOI2008]堵塞的交通
Posted alecli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SHOI2008]堵塞的交通相关的知识,希望对你有一定的参考价值。
题意
思考
一道很好的线段树题 (&&) 一道很毒瘤的码农题
一开始完全没想到用线段树来维护这种网格的连通性,后来看题解之后发现实在是妙啊……(满足区间可合并性)
线段树维护的是一段区间的四个端点间两两的连通信息,六个变量,合并时由于要考虑两块是否可合并,还得维护区间中间两点是否连通,两个变量。所以总共是八个变量,合并的时候分类讨论有些复杂,具体见代码。
代码
#include<bits/stdc++.h>
#define ls(pos) pos << 1
#define rs(pos) pos << 1 | 1
using namespace std;
const int N = 200020;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x * f;
}
struct node{
int l, r, u, d, p, q, mid1, mid2;
};
namespace Seg{
int l[N << 2], r[N << 2], u[N << 2], d[N << 2], p[N << 2], q[N << 2], mid1[N << 2], mid2[N << 2];
///l左侧上下 r右侧上下 u上 d下 p左上右下 q左下右上 mid1第一行中间是否联通 mid2第二行…
void pushup(int pos){
l[pos] = l[ls(pos)] || (u[ls(pos)] && mid1[pos] && l[rs(pos)] && mid2[pos] && d[ls(pos)]);
r[pos] = r[rs(pos)] || (u[rs(pos)] && mid1[pos] && r[ls(pos)] && mid2[pos] && d[rs(pos)]);
u[pos] = (u[ls(pos)] && u[rs(pos)] && mid1[pos]) || (p[ls(pos)] && mid2[pos] && q[rs(pos)]);
d[pos] = (d[ls(pos)] && d[rs(pos)] && mid2[pos]) || (q[ls(pos)] && mid1[pos] && p[rs(pos)]);
p[pos] = (p[ls(pos)] && mid2[pos] && d[rs(pos)]) || (u[ls(pos)] && mid1[pos] && p[rs(pos)]);
q[pos] = (q[ls(pos)] && mid1[pos] && u[rs(pos)]) || (d[ls(pos)] && mid2[pos] && q[rs(pos)]);
}
void build(int pos, int ll, int rr){
if(ll == rr){
mid1[pos] = mid2[pos] = u[pos] = d[pos] = 1;
return ;
}
int mid = (ll + rr) >> 1;
build(ls(pos), ll, mid);
build(rs(pos), mid+1, rr);
}
void modify(int pos, int ll, int rr, int x, int v){///竖
if(ll == rr){
l[pos] = r[pos] = p[pos] = q[pos] = v;
return ;
}
int mid = (ll + rr) >> 1;
if(x <= mid) modify(ls(pos), ll, mid, x, v);
else modify(rs(pos), mid+1, rr, x, v);
pushup(pos);
}
void modify2(int pos, int ll, int rr, int op, int x, int v){///横
int mid = (ll + rr) >> 1;
if(mid == x){
if(op == 1) mid1[pos] = v;
else mid2[pos] = v;
pushup(pos);
return ;
}
if(x <= mid) modify2(ls(pos), ll, mid, op, x, v);
else modify2(rs(pos), mid+1, rr, op, x, v);
pushup(pos);
}
node query(int pos, int ll, int rr, int x, int y){
if(x <= ll && rr <= y){
node ans = (node){l[pos], r[pos], u[pos], d[pos], p[pos], q[pos], mid1[pos], mid2[pos]};
return ans;
}
int mid = (ll + rr) >> 1;
if(y <= mid) return query(ls(pos), ll, mid, x, y);
else if(x > mid) return query(rs(pos), mid+1, rr, x, y);
else{
node ans = (node){l[pos], r[pos], u[pos], d[pos], p[pos], q[pos], mid1[pos], mid2[pos]};
node ansl = query(ls(pos), ll, mid, x, y), ansr = query(rs(pos), mid+1, rr, x, y);
ans.l = ansl.l || (ansl.u && ans.mid1 && ansr.l && ans.mid2 && ansl.d);
ans.r = ansr.r || (ansr.u && ans.mid1 && ansl.r && ans.mid2 && ansr.d);
ans.u = (ansl.u && ansr.u && ans.mid1) || (ansl.p && ans.mid2 && ansr.q);
ans.d = (ansl.d && ansr.d && ans.mid2) || (ansl.q && ans.mid1 && ansr.p);
ans.p = (ansl.p && ans.mid2 && ansr.d) || (ansl.u && ans.mid1 && ansr.p);
ans.q = (ansl.q && ans.mid1 && ansr.u) || (ansl.d && ans.mid2 && ansr.q);
return ans;
}
}
}
using namespace Seg;
int n;
int main(){
n = read();
build(1, 1, n);
while(233){
char op[20]; cin >> op + 1;
if(op[1] == ‘E‘) break;
int r1 = read(), c1 = read(), r2 = read(), c2 = read();
if(c1 > c2) swap(c1, c2), swap(r1, r2);
if(op[1] == ‘O‘){
if(c1 == c2) modify(1, 1, n, c1, 1);
else modify2(1, 1, n, r1, c1, 1);
}
if(op[1] == ‘C‘){
if(c1 == c2) modify(1, 1, n, c1, 0);
else modify2(1, 1, n, r1, c1, 0);
}
if(op[1] == ‘A‘){
int ans = 0;
node l = query(1, 1, n, 1, c1), mid = query(1, 1, n, c1, c2), r = query(1, 1, n, c2, n);
if(r1 == 1 && r2 == 1) ans = mid.u || (l.r && mid.q) || (r.l && mid.p) || (l.r && mid.d && r.l);
if(r1 == 2 && r2 == 2) ans = mid.d || (l.r && mid.p) || (r.l && mid.q) || (l.r && mid.u && r.l);
if(r1 == 1 && r2 == 2) ans = mid.p || (l.r && mid.d) || (r.l && mid.u) || (l.r && mid.q && r.l);
if(r1 == 2 && r2 == 1) ans = mid.q || (l.r && mid.u) || (r.l && mid.d) || (l.r && mid.p && r.l);
if(ans) puts("Y");
else puts("N");
}
}
return 0;
}
总结
这题细节很多,也比较锻炼码力吧,我觉得以后遇到这种题还是要有足够的把握才写正解,写正解的话也要注意:把变量的用途尽量注释出来,写程序时多多检查,多调试,保证每步要正确,不然查错的时候??
以上是关于[SHOI2008]堵塞的交通的主要内容,如果未能解决你的问题,请参考以下文章