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

    题目描述

    有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
    以被看成是一个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”作为
    结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。

    输出格式

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

    输入输出样例

    输入样例#1:

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

    输出样例#1:

    Y
    N


    这题真TM恶心

    线段树维护区间的连通性

    需要维护以下的量

    (设A,B,C,D是一段区间的左上端点,右上端点,左下端点,右下端点)

    upp 区间的中间两列在第1行是否连通

    dow 区间的中间两列在第2行是否连通

    (A B)
    (C D)
    l A -> C 是否连通
    r B -> D 是否连通
    u A -> B 是否连通
    d C -> D 是否连通
    ud A -> D 是否连通
    du B -> C 是否连通
    然后区间合并肥肠恶心
    一开始自己瞎写姿势不是很对一直30
    之后对着题解改了半天发现跟题解差不多了==

    #include<cstdio>
    #include<algorithm>
    const int M = 100005 ;
    using namespace std ;
    inline int read() { 
        char c = getchar() ; int x = 0 , w = 1 ;
        while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
        while(c>='0'&&c<='9') { x = x*10+c - '0'; c = getchar() ; }
        return x*w ;
    }
    # define ls now<<1
    # define rs now<<1|1
    struct Node {
    	bool upp , dow ;
    	bool l , r , u , d , ud , du ;
    }t[M<<2] ;
    inline void pushup(Node &t , Node tl , Node tr) {
    	t.l = tl.l | (tl.u & t.upp & tr.l & t.dow & tl.d) ;
    	t.r = tr.r | (tr.u & t.upp & tl.r & t.dow & tr.d) ;
    	t.u = (tl.u & t.upp & tr.u) | (tl.ud & t.dow & tr.du) ;
    	t.d = (tl.d & t.dow & tr.d) | (tl.du & t.upp & tr.ud) ;
        t.ud = (tl.u & t.upp & tr.ud) | (tl.ud & t.dow & tr.d) ;
        t.du = (tl.d & t.dow & tr.du) | (tl.du & t.upp & tr.u) ;
    }
    void Build(int l , int r , int now) {
    	if(l == r) {
    		t[now].upp = t[now].dow = t[now].u = t[now].d = 1 ;
    		return ;
    	}
    	int mid = (l + r)>>1 ;
    	Build(l , mid , ls) ; Build(mid + 1 , r , rs) ;
    }
    void Changeh(int x , int h , int val , int l , int r , int now) {
    	int mid = (l + r)>>1 ;
    	if(mid == x) {
    		if(h == 1) t[now].upp = val ;
    		else t[now].dow = val ;
    		pushup(t[now] , t[ls] , t[rs]) ;
    		return ;
    	}
    	if(mid >= x) Changeh(x , h , val , l , mid , ls) ;
    	else Changeh(x , h , val , mid + 1 , r , rs) ;
    	pushup(t[now] , t[ls] , t[rs]) ;
    }
    void Changel(int x , int val , int l , int r , int now) {
    	if(l == r) {
    		t[now].l = t[now].r = t[now].ud = t[now].du = val ;
    		return ;
    	}
    	int mid = (l + r)>>1 ;
    	if(mid >= x) Changel(x , val , l , mid , ls) ;
    	else Changel(x , val , mid + 1 , r , rs) ;
    	pushup(t[now] , t[ls] , t[rs]) ;
    }
    Node query(int L , int R , int l , int r , int now) {
    	if(l >= L && r <= R) return t[now] ;
    	int mid = (l + r)>>1 ;
    	if(mid >= R) return query(L , R , l , mid , ls) ;
    	else if(mid < L) return query(L , R , mid + 1 , r , rs) ;
    	else {
    		Node temp = t[now] ;
    		pushup(temp , query(L , mid , l , mid , ls) , query(mid + 1 , R , mid + 1 , r , rs)) ;
    	    return temp ;
    	}
    }
    int main() {
    	int n = read() ; Build(1 , n , 1) ;
    	char s[15] ; int r1 , r2 , c1 , c2 ;
    	scanf("%s",s) ;
    	while(s[0] != 'E') {
    		r1 = read() , c1 = read() , r2 = read() , c2 = read() ;
    		if(c1 > c2) swap(c1 , c2) , swap(r1 , r2) ;
    		if(s[0] == 'O') {
    			if(r1 == r2) Changeh(c1 , r1 , 1 , 1 , n , 1) ;
    			else Changel(c1 , 1 , 1 , n , 1) ;
    		}
    		else if(s[0] == 'C') {
    			if(r1 == r2) Changeh(c1 , r1 , 0 , 1 , n , 1) ;
    			else Changel(c1 , 0 , 1 , n , 1) ; 
    		}
    		else if(s[0] == 'A') {
    			bool Ans = 0 ;
    			Node l = query(1 , c1 , 1 , n , 1) , x = query(c1 , c2 , 1 , n , 1) , r = query(c2 , n , 1 , n , 1) ;
    		    if(r1 == 1 && r2 == 1) Ans = x.u | (l.r & x.du) | (x.ud & r.l) | (l.r & x.d & r.l) ;
    		    else if(r1 == 1 && r2 == 2) Ans = x.ud | (l.r & x.d) | (x.u & r.l) | (l.r & x.du & r.l) ;
    		    else if(r1 == 2 && r2 == 1) Ans = x.du | (l.r & x.u) | (x.d & r.l) | (l.r & x.ud & r.l) ;
    		    else if(r1 == 2 && r2 == 2) Ans = x.d | (l.r & x.ud) | (x.du & r.l) | (l.r & x.u & r.l) ;
    		    printf(Ans ? "Y
    " : "N
    ") ;
    		}
    		scanf("%s",s) ;
    	}
    	return 0 ;
    }
    
  • 相关阅读:
    Navigator与UserAgent笔记
    linux常用命令 查看文件
    linux常用命令 ps
    linux grep命令详解
    svn突然不能用了!
    Macrotask Queue和Microtask Quque
    base.css
    跨域资源共享 CORS 详解
    react按需加载(getComponent优美写法),并指定输出模块名称解决缓存(getComponent与chunkFilename)
    更新阶段的生命周期
  • 原文地址:https://www.cnblogs.com/beretty/p/9488330.html
Copyright © 2011-2022 走看看