zoukankan      html  css  js  c++  java
  • [bzoj1018][SHOI2008]堵塞的交通traffic【线段树】

    【题目描述】

    Description

      有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
    以被看成是一个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;

    Input

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

    Output

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

    Sample Input

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

    Sample Output

    Y
    N

    HINT

    Source

    【题解】

        思路很妙。

        考虑用线段树维护连通性。

        记 can[2][2] 表示左 上(下) 到右 上(下) 是否连通

        这东西可以用线段树维护查询与更改。

        考虑一条路线,回头(180°转弯)最多有2次(最两端),形状为:

        —— —— ——  S             —— —— —— —— —— —— ——

        |                                        |                                                        |

        —— —— —— —— ——                                        T —— ——

        之类。

        所以先把S,T走到不换行能到的最外侧,然后线段树查询连通性。

    /* --------------
        user Vanisher
        problem bzoj-1018 
    ----------------*/
    # include <bits/stdc++.h>
    # define 	ll 		long long
    # define 	N 		100010
    using namespace std;
    int read(){
    	int tmp=0, fh=1; char ch=getchar();
    	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    	return tmp*fh;
    }
    struct Tag{
    	int o[2][2];
    };
    struct node{
    	int pr,l,r;
    	Tag can;
    }T[N*3];
    int o[2][N],place,n;
    char s[11];
    Tag mixed(Tag a, Tag b, int lim){	
    	Tag now={0,0,0,0};
    	for (int i=0; i<=1; i++)
    		if (o[i][lim]==true){
    			if (a.o[0][i]&&b.o[i][0]) now.o[0][0]=true;
    			if (a.o[0][i]&&b.o[i][1]) now.o[0][1]=true;
    			if (a.o[1][i]&&b.o[i][0]) now.o[1][0]=true;
    			if (a.o[1][i]&&b.o[i][1]) now.o[1][1]=true;
    		}
    	return now;
    }
    int build(int l, int r){
    	int p=++place;
    	T[p].l=l; T[p].r=r;
    	if (l==r)
    		T[p].can.o[0][0]=T[p].can.o[1][1]=true;
    		else {
    			int mid=(l+r)/2;
    			build(l,mid);
    			T[p].pr=build(mid+1,r);
    		}
    	return p;
    }
    void modify1(int p, int x, int tag){
    	if (T[p].l==T[p].r){
    		T[p].can.o[0][1]=T[p].can.o[1][0]=tag;
    		return;
    	}
    	int mid=(T[p].l+T[p].r)/2;
    	if (mid>=x) modify1(p+1,x,tag);
    		else modify1(T[p].pr,x,tag);
    	T[p].can=mixed(T[p+1].can,T[T[p].pr].can,mid);
    }
    void modify0(int p, int x){
    	if (T[p].r==x) return;
    	int mid=(T[p].l+T[p].r)/2;
    	if (mid>=x) modify0(p+1,x);
    		else modify0(T[p].pr,x);
    	T[p].can=mixed(T[p+1].can,T[T[p].pr].can,mid);
    }
    int queryl(int p, int x, int tag){
    	if (T[p].r==x&&T[p].can.o[tag][tag]==true) return T[p].l;
    	int mid=(T[p].l+T[p].r)/2;
    	if (mid<x){
    		int num=queryl(T[p].pr,x,tag);
    		if (num!=mid+1) return num;
    		if (o[tag][mid]==false) return num;
    		return queryl(p+1,mid,tag);
    	}
    	else return queryl(p+1,x,tag);
    }
    int queryr(int p, int x, int tag){
    	if (T[p].l==x&&T[p].can.o[tag][tag]==true) return T[p].r;
    	int mid=(T[p].l+T[p].r)/2;
    	if (mid>=x){
    		int num=queryr(p+1,x,tag);
    		if (num!=mid) return num;
    		if (o[tag][mid]==false) return num;
    		return queryr(T[p].pr,mid+1,tag);
    	}
    	else return queryr(T[p].pr,x,tag);
    }
    Tag query(int p, int l, int r){
    	if (T[p].l==l&&T[p].r==r)
    		return T[p].can;
    	int mid=(T[p].l+T[p].r)/2;
    	if (mid>=r) return query(p+1,l,r);
    		else if (mid<l) return query(T[p].pr,l,r);
    			else {
    				Tag a=query(p+1,l,mid), b=query(T[p].pr,mid+1,r);
    				return mixed(a,b,mid);
    			}
    }
    int main(){
    	n=read();
    	int rt=build(1,n);
    	scanf("
    %s",s+1);
    	while (s[1]!='E'){
    		int dx1=read()-1, dy1=read(), dx2=read()-1, dy2=read();
    		if (dy1>dy2) swap(dy1,dy2), swap(dx1,dx2);
    		if (s[1]=='O'){
    			if (dx1!=dx2) modify1(rt,dy1,1);
    				else {
    					o[dx1][dy1]=true;
    					modify0(rt,dy1);
    				}
    		}
    		if (s[1]=='C'){
    			if (dx1!=dx2) modify1(rt,dy1,0);
    				else{
    					o[dx1][dy1]=false;
    					modify0(rt,dy1);
    				}
    		}
    		if (s[1]=='A'){
    			dy1=queryl(rt,dy1,dx1);
    			dy2=queryr(rt,dy2,dx2);
    			Tag num=query(rt,dy1,dy2);
    			if (num.o[dx1][dx2]==true)
    				printf("Y
    "); else printf("N
    ");
    		} 
    		scanf("
    %s",s+1);
    	} 
    	return 0;
    }

  • 相关阅读:
    .net批量插入SqlServer数据库的方法:
    Google主页中国元宵节
    左岸读书你是想读书,还是想读完书?
    Google主页中国著名教育家和画家 丰子恺先生 诞辰114周年
    【转载】图的遍历
    Google主页爱尔兰作家 布拉姆斯托克诞辰165周年
    诺基亚黯然关闭其在欧洲的最后一个手机工厂的背后
    [POJ 1012] Joseph(约瑟夫)
    台湾南投3.27地震
    左岸读书语不惊人死不休(95)
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9136005.html
Copyright © 2011-2022 走看看