SHOI2008 堵塞的交通 线段树

版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82152748

传送门

线段树三连。
这是一道让人误解为水题的线段树题。
实则让我想骂出题人出了这么道大毒瘤。

题意:维护2*n的网格区域中点的连通性。
题解:线段树维护连通性。

关于代码中变变量的含义。

把上下两个城市看作线段树中的一个点
合并两个区间时,只看这两个区间的左,右端点,更新合并区间的连通性。这个很好想,不过实现起来…嘿嘿嘿
记录横向的线段,用于合并时判断。由于修改都是单条路修改,记录起来也不太难。
总之就是要多画图,把两点连通性的所有情况给画出来。
可以见这里,讲得更清楚。

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100001;

int n;

inline int read(){
	int k = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
	return k * f;
}

struct Segment_Tree{
	#define mid ((l + r) >> 1)
	bool r1[MAXN], r2[MAXN]; //上下公路,向右
	struct Node{
		int l, r;
		bool l1r1, l1r2, l1l2, l2r1, l2r2, r1r2;
	}t[MAXN << 2];
	inline void Pushup(Node *u, Node ls, Node rs){
		u->l = ls.l, u->r = rs.r;
		u->l1l2 =  ls.l1l2  || (ls.l1r1 && r1[ls.r] && rs.l1l2 && r2[ls.r] && ls.l2r2);
		u->r1r2 =  rs.r1r2  || (rs.l1r1 && r1[ls.r] && ls.r1r2 && r2[ls.r] && rs.l2r2);
		u->l1r1 = (ls.l1r1 && r1[ls.r] && rs.l1r1) || (ls.l1r2 && r2[ls.r] && rs.l2r1);
		u->l2r2 = (ls.l2r1 && r1[ls.r] && rs.l1r2) || (ls.l2r2 && r2[ls.r] && rs.l2r2);
		u->l1r2 = (ls.l1r1 && r1[ls.r] && rs.l1r2) || (ls.l1r2 && r2[ls.r] && rs.l2r2);
		u->l2r1 = (ls.l2r1 && r1[ls.r] && rs.l1r1) || (ls.l2r2 && r2[ls.r] && rs.l2r1);
	}
	inline void Build(int u, int l, int r){
		if(l == r){t[u].l = t[u].r = l; t[u].l1r1 = t[u].l2r2 = true; return;}
		Build(u << 1, l, mid), Build(u << 1 | 1, mid + 1, r);
		Pushup(&t[u], t[u << 1], t[u << 1 | 1]);
	}
	inline void Modify1(int u, int l, int r, int x, bool opt){ //处理竖着的
		if(l == r){t[u].l1l2 = t[u].r1r2 = t[u].l1r2 = t[u].l2r1 = opt; return;}
		if(x <= mid) Modify1(u << 1, l, mid, x, opt);
		if(x > mid) Modify1(u << 1 | 1, mid + 1, r, x, opt);
		Pushup(&t[u], t[u << 1], t[u << 1 | 1]);
	}
	inline void Modify2(int u, int l, int r, int x, bool y, bool opt){ //处理横着的
		if(x == mid) (y == 0) ? r1[x] = opt : r2[x] = opt;
		else if(x < mid) Modify2(u << 1, l, mid, x, y, opt);
		else if(x > mid) Modify2(u << 1 | 1, mid + 1, r, x, y, opt);
		Pushup(&t[u], t[u << 1], t[u << 1 | 1]);
	}
	inline Node Query(int u, int l, int r, int L, int R){ //询问c1, c2之间区间的联通性
		if(l >= L && r <= R) return t[u];
		if(R <= mid) return Query(u << 1, l, mid, L, R);
		if(L > mid) return Query(u << 1 | 1, mid + 1, r, L, R);
		Node Tmp1 = Query(u << 1, l, mid, L, mid), Temp;
		Node Tmp2 = Query(u << 1 | 1, mid + 1, r, mid + 1, R);
		Pushup(&Temp, Tmp1, Tmp2); return Temp;
	}
	inline void Ask(int ra, int ca, int rb, int cb){
		Node L = Query(1, 1, n, 1, ca);
		Node M = Query(1, 1, n, ca, cb);
		Node R = Query(1, 1, n, cb, n);
		bool b1 = false, b2 = false, b3 = false, b4 = false;
		if(ra == 0 && rb == 0){
			b1 = M.l1r1;
			b2 = L.r1r2 && M.l2r1;
			b3 = R.l1l2 && M.l1r2;
			b4 = L.r1r2 && M.l2r2 && R.l1l2;
		} else if(ra == 0 && rb == 1){
			b1 = M.l1r2;
			b2 = L.r1r2 && M.l2r2;
			b3 = R.l1l2 && M.l1r1;
			b4 = L.r1r2 && M.l2r1 && R.l1l2;
		} else if(ra == 1 && rb == 0){
			b1 = M.l2r1;
			b2 = L.r1r2 && M.l1r1;
			b3 = R.l1l2 && M.l2r2;
			b4 = L.r1r2 && M.l1r2 && R.l1l2;
		} else if(ra == 1 && rb == 1){
			b1 = M.l2r2;
			b2 = L.r1r2 && M.l1r2;
			b3 = R.l1l2 && M.l2r1;
			b4 = L.r1r2 && M.l1r1 && R.l1l2;
		}
		if(b1 || b2 || b3 || b4){
			puts("Y");
		} else{
			puts("N");
		}
		return;
	}
	#undef mid
}T;

int main(){
	freopen("in.txt", "r", stdin);
	n = read(); char opt[10];
	T.Build(1, 1, n);
	while(1){
		scanf("%s", opt);
		if(opt[0] == 'E') break;
		int ra = read() - 1, ca = read(), rb = read() - 1, cb = read();
		if(ca > cb) swap(ra, rb), swap(ca, cb);
		if(opt[0] == 'O' || opt[0] == 'C'){
			int w = (opt[0] == 'O');
			if(ra == rb){ //横着的
				T.Modify2(1, 1, n, ca, ra, w);
			} else{ //竖着的
				T.Modify1(1, 1, n, ca, w);
			}
		}
		else{
			T.Ask(ra, ca, rb, cb);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/DyingShu/article/details/82152748
今日推荐