zoukankan      html  css  js  c++  java
  • 【BZOJ 1018】【SHOI 2008】堵塞的交通traffic

    http://www.lydsy.com/JudgeOnline/problem.php?id=1018
    线段树维护连通性。
    把每一列看成一个节点,对于线段树上的每一个节点,维护8个信息,前6个字面意思很好理解,sd0和sd1分别代表这个节点所代表的列区间的最右端再往右的第1/2行是否有道路连出去。
    注意一个节点上的信息表示只用这个节点所代表区间内的边是否连通,这样单点修改后再维护一下信息是可行的。
    对于询问,因为每个节点维护的信息只是区间内部的边的连通性,所以要查询(left[1,c_1 ight],left[c_1,c_2 ight],left[c_2,n ight],c_1leq c_2) 3个区间的连通性,暴力分类讨论一下就可以了。
    注意分类讨论一定要全面qwq,尤其是不在(left[c_1,c_2 ight])内的边对左右端点的列的上下两行的连通性造成干扰时,(left[c_1,c_2 ight])内的连通性受到的影响非常大,就需要十分严格的分类讨论。
    时间复杂度(O(nlog n))
    我的常数好大啊qwq

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 100003;
    
    struct node {
    	bool luru, lurd, ldru, ldrd, luld, rurd, sd0, sd1;
    	void clear() {luru = lurd = ldru = ldrd = luld = rurd = sd0 = sd1 = false;}
    	void init() {luru = ldrd = sd0 = sd1 = true;}
    	void copy(node *r) {luru = r->luru; lurd = r->lurd; ldru = r->ldru; ldrd = r->ldrd; luld = r->luld; rurd = r->rurd; sd0 = r->sd0; sd1 = r->sd1;}
    } T[N << 2], q1, q2, q3, q4;
    
    int n, r1, c1, r2, c2;
    
    void pushup(node *r, node *c0, node *c1) {
    	r->sd0 = c1->sd0; r->sd1 = c1->sd1;
    	r->luru = (c0->luru && c1->luru && c0->sd0 || c0->lurd && c1->ldru && c0->sd1);
    	r->lurd = (c0->luru && c1->lurd && c0->sd0 || c0->lurd && c1->ldrd && c0->sd1);
    	r->ldru = (c0->ldru && c1->luru && c0->sd0 || c0->ldrd && c1->ldru && c0->sd1);
    	r->ldrd = (c0->ldru && c1->lurd && c0->sd0 || c0->ldrd && c1->ldrd && c0->sd1);
    	r->luld = (c0->luld || c0->sd0 && c0->sd1 && c0->luru && c0->ldrd && c1->luld);
    	r->rurd = (c1->rurd || c0->sd0 && c0->sd1 && c1->luru && c1->ldrd && c0->rurd);
    }
    
    void BuildTree(int rt, int l, int r) {
    	if (l == r) {T[rt].luru = T[rt].ldrd = true; return;}
    	int mid = (l + r) >> 1;
    	BuildTree(rt << 1, l, mid);
    	BuildTree(rt << 1 | 1, mid + 1, r);
    	pushup(T + rt, T + (rt << 1), T + (rt << 1 | 1));
    }
    
    void update(int rt, int l, int r, int pos, int flag) {
    	if (l == r) {
    		switch (flag) {
    			case -3: T[rt].luld = T[rt].rurd = T[rt].lurd = T[rt].ldru = false; break;
    			case 3: T[rt].luld = T[rt].rurd = T[rt].lurd = T[rt].ldru = true; break;
    			case -2: T[rt].sd1 = false; break;
    			case -1: T[rt].sd0 = false; break;
    			case 2: T[rt].sd1 = true; break;
    			case 1: T[rt].sd0 = true; break;
    		}
    		return;
    	}
    	int mid = (l + r) >> 1;
    	if (pos <= mid) update(rt << 1, l, mid, pos, flag);
    	else update(rt << 1 | 1, mid + 1, r, pos, flag);
    	pushup(T + rt, T + (rt << 1), T + (rt << 1 | 1));
    }
    
    void merge(int rt, int l, int r, int L, int R, node *rr) {
    	if (L <= l && r <= R) {pushup(&q4, rr, T + rt); rr->copy(&q4); return;}
    	int mid = (l + r) >> 1;
    	if (L <= mid) merge(rt << 1, l, mid, L, R, rr);
    	if (R > mid) merge(rt << 1 | 1, mid + 1, r, L, R, rr);
    }
    
    bool check() {
    	if (c1 > c2) {swap(r1, r2); swap(c1, c2);}
    	q1.clear(); q2.clear(); q3.clear();
    	q1.init(); q2.init(); q3.init();
    	merge(1, 1, n, 1, c1, &q1);
    	merge(1, 1, n, c1, c2, &q2);
    	merge(1, 1, n, c2, n, &q3);
    	
    	if (q1.rurd) q2.luld = true; if (q3.luld) q2.rurd = true;
    	if (q2.luld && q2.ldru || q2.rurd && q2.lurd || q2.luld && q2.rurd && q2.ldrd) q2.luru = true;
    	if (q2.luld && q2.lurd || q2.rurd && q2.ldru || q2.luld && q2.rurd && q2.luru) q2.ldrd = true;
    	if (q2.luld && q2.ldrd || q2.rurd && q2.luru || q2.luld && q2.rurd && q2.ldru) q2.lurd = true;
    	if (q2.luld && q2.luru || q2.rurd && q2.ldrd || q2.luld && q2.rurd && q2.lurd) q2.ldru = true;
    	
    	if (r1 == 1 && r2 == 1)	return q2.luru;
    	if (r1 == 1 && r2 == 2) return q2.lurd;
    	if (r1 == 2 && r2 == 1) return q2.ldru;
    	if (r1 == 2 && r2 == 2) return q2.ldrd;
    }
    
    char op[23];
    
    int main() {
    	scanf("%d", &n);
    	BuildTree(1, 1, n);
    	int tt = 0;
    	while (true) {
    		scanf("%s", op);
    		if (op[0] == 'E') break;
    		scanf("%d%d%d%d", &r1, &c1, &r2, &c2);
    		switch (op[0]) {
    			case 'C':
    				if (c1 == c2) update(1, 1, n, c1, -3);
    				else update(1, 1, n, min(c1, c2), -r1);
    			break;
    			case 'O':
    				if (c1 == c2) update(1, 1, n, c1, 3);
    				else update(1, 1, n, min(c1, c2), r1);
    			break;
    			case 'A':
    				puts(check() ? "Y" : "N");
    			break;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    201521123031 《Java程序设计》第14周学习总结
    201521123031 《Java程序设计》第13周学习总结
    软工个人作业5——软件工程总结
    软工网络15个人作业4——alpha阶段个人总结
    软工网络15个人作业3——案例分析
    软件工程网络15结对编程作业
    软工网络15个人阅读作业2——提问题
    软件工程网络15个人阅读作业1(201521123036 曾艺佳)
    Java课程设计
    Java课程设计-学生基本信息管理 201521123036
  • 原文地址:https://www.cnblogs.com/abclzr/p/6610478.html
Copyright © 2011-2022 走看看