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

    【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

    题解:先不考虑从两边走的情况,直接上线段树的区间合并即可。用f[0/1][0/1]表示从左上/左下能否走到右上/右下。

    那么如果考虑从两边绕的情况呢?一定是贪心的选取第一个能拐的点就直接拐,所以在线段树上找到第一个拐点然后判断中间是否全部连通即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=100010;
    int n,pre,nxt;
    struct node
    {
    	bool f[2][2],g[3],lp;
    	node () {memset(f,0,sizeof(f)),memset(g,0,sizeof(g)),lp=0;}
    }s[maxn<<2];
    node mix(node a,node b)
    {
    	node c;
    	c.f[0][0]=(a.f[0][0]&b.f[0][0])|(a.f[0][1]&b.f[1][0])|(a.f[0][0]&b.f[1][0]&b.lp)|(a.f[0][1]&b.f[0][0]&b.lp);
    	c.f[0][1]=(a.f[0][0]&b.f[0][1])|(a.f[0][1]&b.f[1][1])|(a.f[0][0]&b.f[1][1]&b.lp)|(a.f[0][1]&b.f[0][1]&b.lp);
    	c.f[1][0]=(a.f[1][0]&b.f[0][0])|(a.f[1][1]&b.f[1][0])|(a.f[1][0]&b.f[1][0]&b.lp)|(a.f[1][1]&b.f[0][0]&b.lp);
    	c.f[1][1]=(a.f[1][0]&b.f[0][1])|(a.f[1][1]&b.f[1][1])|(a.f[1][0]&b.f[1][1]&b.lp)|(a.f[1][1]&b.f[0][1]&b.lp);
    	c.g[0]=a.g[0]&b.g[0],c.g[1]=a.g[1]&b.g[1],c.g[2]=a.g[2]|b.g[2],c.lp=a.lp;
    	return c;
    }
    char str[20];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void updata(int l,int r,int x,int a,int b,int c)
    {
    	if(l==r)
    	{
    		s[x].g[b]=c,s[x].f[0][0]=s[x].g[0],s[x].f[1][1]=s[x].g[1],s[x].lp=s[x].g[2];
    		s[x].f[0][1]=s[x].g[2]&s[x].f[1][1],s[x].f[1][0]=s[x].g[2]&s[x].f[0][0];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,lson,a,b,c);
    	else	updata(mid+1,r,rson,a,b,c);
    	s[x]=mix(s[lson],s[rson]);
    }
    void getpre(int l,int r,int x,int a)
    {
    	if(l>a||pre>=r||!s[x].g[2])	return ;
    	if(l==r)
    	{
    		pre=l;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	getpre(mid+1,r,rson,a),getpre(l,mid,lson,a);
    }
    void getnxt(int l,int r,int x,int a)
    {
    	if(r<a||nxt<=l||!s[x].g[2])	return ;
    	if(l==r)
    	{
    		nxt=l;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	getnxt(l,mid,lson,a),getnxt(mid+1,r,rson,a);
    }
    node query(int l,int r,int x,int a,int b)
    {
    	if(a>b)
    	{
    		node tmp;
    		tmp.f[0][0]=tmp.f[1][1]=tmp.g[0]=tmp.g[1]=1;
    		return tmp;
    	}
    	if(a<=l&&r<=b)	return s[x];
    	int mid=(l+r)>>1;
    	if(b<=mid)	return query(l,mid,lson,a,b);
    	if(a>mid)	return query(mid+1,r,rson,a,b);
    	return mix(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
    }
    int main()
    {
    	n=rd();
    	int a1,b1,a2,b2;
    	while(1)
    	{
    		scanf("%s",str);
    		if(str[0]=='E')	return 0;
    		a1=rd()-1,b1=rd(),a2=rd()-1,b2=rd();
    		if(b1>b2||(b1==b2&&a1>a2))	swap(a1,a2),swap(b1,b2);
    		if(str[0]=='C')
    		{
    			if(b1==b2)	updata(1,n,1,b1,2,0);
    			else	updata(1,n,1,b1,a1,0);
    		}
    		if(str[0]=='O')
    		{
    			if(b1==b2)	updata(1,n,1,b1,2,1);
    			else	updata(1,n,1,b1,a1,1);
    		}
    		if(str[0]=='A')
    		{
    			node tmp;
    			tmp=query(1,n,1,b1,b2-1);
    			if(tmp.f[a1][a2])	printf("Y
    ");
    			else
    			{
    				pre=0,getpre(1,n,1,b1);
    				nxt=n+1,getnxt(1,n,1,b2);
    				node t1,t2;
    				if(pre)	t1=query(1,n,1,pre,b1-1);
    				if(nxt!=n+1)	t2=query(1,n,1,b2,nxt-1);
    				if(t1.g[0]&t1.g[1]&tmp.f[a1^1][a2])	printf("Y
    ");
    				else	if(t2.g[0]&t2.g[1]&tmp.f[a1][a2^1])	printf("Y
    ");
    				else	if(t1.g[0]&t1.g[1]&t2.g[0]&t2.g[1]&tmp.f[a1^1][a2^1])	printf("Y
    ");
    				else	printf("N
    ");
    			}
    		}
    	}
    }//4 Open 1 1 1 2 Open 1 1 2 1 Open 2 1 2 2 Open 2 2 2 3 Open 2 3 2 4 Open 1 4 2 4 Open 1 3 1 4 Ask 1 2 1 3
  • 相关阅读:
    linux -- 基于zookeeper搭建yarn的HA高可用集群
    Linux -- 之HDFS实现自动切换HA(全新HDFS)
    Hadoop格式化 From hu-hadoop1/192.168.11.11 to hu-hadoop2:8485 failed on connection exception: java.net.
    Directory /home/hdfs/name is in an inconsistent state: storage directory does not exist or is not a
    react学习01
    单页面应用(spa)引入百度地图(Cannot read property 'dc' of undefined)
    npm 发布包
    Vue学习-01
    echarts3.0使用总结
    webpack学习--创建一个webpack打包流程
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7425137.html
Copyright © 2011-2022 走看看