zoukankan      html  css  js  c++  java
  • [BZOJ1018][SHOI2008]堵塞的交通traffic

    [BZOJ1018][SHOI2008]堵塞的交通traffic

    试题描述

    有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式: Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了; Open r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被疏通了; Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一条路径使得这两条城市连通,则返回Y,否则返回N;

    输入

    第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为结束。我们假设在一开始所有的道路都是堵塞的。 对30%测试数据,我们保证C小于等于1000,信息条数小于等于1000; 对100%测试数据,我们保证 C小于等于100000,信息条数小于等于100000。

    输出

    对于每个查询,输出一个“Y”或“N”。

    输入示例

    2
    Open 1 1 1 2
    Open 1 2 2 2
    Ask 1 1 2 2
    Ask 2 1 2 2
    Exit

    输出示例

    Y
    N

    数据规模及约定

    见“输入

    题解

    用线段树维护连通性。每个区间维护 左上右上、左上右下、左上左下、左下右上、左下右下、右上右下 的连通性,合并两个区间时分类讨论一下怎么从起点走到目标位置。

    以下代码 0, 1, 2, 3 分别表示 左上、右上、左下、右下。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define maxn 100010
    #define maxlog 50
    int n, maxo;
    char tp[10];
    bool Oc[2][maxn], Or[maxn];
    
    bool con[4][4][maxn<<2];
    void combine(int o, int lc, int rc, int M) {
    	con[0][1][o] = (con[0][1][lc] & Oc[0][M] & con[0][1][rc]) | (con[0][3][lc] & Oc[1][M] & con[1][2][rc]);
    	con[0][3][o] = (con[0][1][lc] & Oc[0][M] & con[0][3][rc]) | (con[0][3][lc] & Oc[1][M] & con[2][3][rc]);
    	con[0][2][o] = con[0][2][lc] | (con[0][1][lc] & Oc[0][M] & con[0][2][rc] & Oc[1][M] & con[2][3][lc]);
    	con[1][2][o] = (con[1][2][lc] & Oc[0][M] & con[0][1][rc]) | (con[2][3][lc] & Oc[1][M] & con[1][2][rc]);
    	con[1][3][o] = con[1][3][rc] | (con[0][1][rc] & Oc[0][M] & con[1][3][lc] & Oc[1][M] & con[2][3][rc]);
    	con[2][3][o] = (con[1][2][lc] & Oc[0][M] & con[0][3][rc]) | (con[2][3][lc] & Oc[1][M] & con[2][3][rc]);
    	return ;
    }
    void build(int L, int R, int o) {
    	maxo = max(maxo, o);
    	if(L == R) con[0][1][o] = con[2][3][o] = 1;
    	else {
    		int M = L + R >> 1, lc = o << 1, rc = lc | 1;
    		build(L, M, lc); build(M+1, R, rc);
    		combine(o, lc, rc, M);
    	}
    	return ;
    }
    void update(int tp, int L, int R, int o, int r, int c, int v) {
    	if(L == R) {
    		if(tp) con[0][2][o] = con[1][3][o] = con[0][3][o] = con[1][2][o] = Or[c] = v;
    		else Oc[r][c] = v;
    		return ;
    	}
    	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
    	if(c <= M) update(tp, L, M, lc, r, c, v);
    	else update(tp, M+1, R, rc, r, c, v);
    	combine(o, lc, rc, M);
    	return ;
    }
    int cnt, ql, qr, que[maxlog], quer[maxlog];
    void Query(int L, int R, int o) {
    	if(ql <= L && R <= qr) {
    		que[++cnt] = o; quer[cnt] = R;
    		return ;
    	}
    	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
    	if(ql <= M) Query(L, M, lc);
    	if(qr > M) Query(M+1, R, rc);
    	return ;
    }
    bool query(int r1, int c1, int r2, int c2) {
    	if(c1 > c2) swap(r1, r2), swap(c1, c2);
    	
    	bool flag[4]; memset(flag, 0, sizeof(flag));
    	cnt = 0; ql = 1; qr = c1;
    	Query(1, n, 1);
    	for(int i = 0; i < 4; i++)
    		for(int j = i+1; j < 4; j++) con[i][j][0] = con[i][j][que[1]];
    	for(int k = 2; k <= cnt; k++) {
    		combine(maxo + 1, 0, que[k], quer[k-1]);
    		for(int i = 0; i < 4; i++)
    			for(int j = i+1; j < 4; j++) con[i][j][0] = con[i][j][maxo+1];
    	}
    	if(con[1][3][0]) flag[0] = flag[2] = 1;
    	else {
    		if(!r1) flag[0] = 1;
    		else flag[2] = 1;
    	}
    	cnt = 0; ql = c2; qr = n;
    	Query(1, n, 1);
    	for(int i = 0; i < 4; i++)
    		for(int j = i+1; j < 4; j++) con[i][j][0] = con[i][j][que[1]];
    	for(int k = 2; k <= cnt; k++) {
    		combine(maxo + 1, 0, que[k], quer[k-1]);
    		for(int i = 0; i < 4; i++)
    			for(int j = i+1; j < 4; j++) con[i][j][0] = con[i][j][maxo+1];
    	}
    	if(con[0][2][0]) flag[1] = flag[3] = 1;
    	else {
    		if(!r2) flag[1] = 1;
    		else flag[3] = 1;
    	}
    //	printf("%d %d %d %d
    ", r1, c1, r2, c2);
    //	printf("%d %d %d %d
    ", flag[0], flag[1], flag[2], flag[3]);
    	
    	cnt = 0; ql = c1; qr = c2;
    	Query(1, n, 1);
    	for(int i = 0; i < 4; i++)
    		for(int j = i+1; j < 4; j++) con[i][j][0] = con[i][j][que[1]];
    	for(int k = 2; k <= cnt; k++) {
    		combine(maxo + 1, 0, que[k], quer[k-1]);
    		for(int i = 0; i < 4; i++)
    			for(int j = i+1; j < 4; j++) con[i][j][0] = con[i][j][maxo+1];
    	}
    //	printf("%d %d %d %d %d
    ", con[0][1][1], con[0][3][1], con[1][2][1], con[1][3][1], con[0][2][1]);
    	for(int i = 0; i < 4; i += 2)
    		for(int j = 1; j < 4; j += 2) if(flag[i] && flag[j] && con[min(i,j)][max(i,j)][0])
    			return 1;
    	return 0;
    }
    
    int main() {
    	scanf("%d", &n);
    	build(1, n, 1);
    	int top = 0, tot = 0;
    	while(scanf("%s", &tp) == 1) {
    		if(tp[0] == 'E') break;
    		int r1, c1, r2, c2;
    		scanf("%d%d%d%d", &r1, &c1, &r2, &c2);
    		r1--; r2--;
    //		int r1 = read() - 1, c1 = read(), r2 = read() - 1, c2 = read();
    		tot++;
    		if(tp[0] == 'O') {
    			if(r1 == r2) update(0, 1, n, 1, r1, min(c1, c2), 1);
    			else update(1, 1, n, 1, r1, c1, 1);
    		}
    		if(tp[0] == 'C') {
    			if(r1 == r2) update(0, 1, n, 1, r1, min(c1, c2), 0);
    			else update(1, 1, n, 1, r1, c1, 0);
    		}
    		if(tp[0] == 'A') {
    //			if(++top == 192) printf("%d %d %d %d %d
    ", r1, c1, r2, c2, tot);
    			if(query(r1, c1, r2, c2)) printf("Y
    ");
    			else printf("N
    ");
    		}
    	}
    	
    	return 0;
    }
    

    cnbb 我都要调吐了。。。

  • 相关阅读:
    博客园美化-打赏代码
    苹果appID的获取方法
    简体、繁体相互转换
    iOS Socket编程(一)基本概念
    无线通信
    http与https通信
    iOS开发网络篇—发送GET和POST请求(使用NSURLSession)
    iOS开发网络篇—GET请求和POST请求的说明与比较
    iOS开发网络篇—HTTP协议
    Verify the Developer App certificate for your account is trusted on your device.
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5801462.html
Copyright © 2011-2022 走看看