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

    bzoj-1018 SHOI-2008 堵塞的交通traffic

    参考博客:https://www.cnblogs.com/MashiroSky/p/5973686.html

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

    数据范围:$0le Cle 10^5$,$1le Number_{message} le 10^5$。


    想法

    哇哦。。。

    这题真的能想出来?

    我们用线段树维护一个列在$(l,r)$之间的这么$r-l+1$个方格的连通性。

    维护的信息如下图:

    然后如果在同一行的话同理。

    现在,假设从左到右,从上到下,矩阵的四个角依次命名为$s1$,$s2$,$s3$,$s4$。

    我们就维护

    $U$:第一行的$mid$和$mid+1$是否连通。

    $D$:第二行的$mid$和$mid+1$是否连通。

    $l$:$s1$和$s3$是否连通。

    $r$:$s2$和$s4$是否连通。

    $u$:$s1$和$s2$是否连通。

    $d$:$s3$和$s4$是否连通。

    $q$:$s1$和$s4$是否连通。

    $p$:$s2$和$s3$是否连通。

    之后暴力维护就好了。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ls p<<1
    #define rs p<<1|1
    #define N 100010 
    using namespace std;
    struct Node
    {
    	bool U,D,l,r,u,d,p,q;
    }a[N<<2];
    inline void pushup(Node &p,Node l,Node r)
    {
    	p.l = l.l | (l.u & p.U & r.l & p.D & l.d);
    	p.r = r.r | (r.u & p.U & l.r & p.D & r.d);
    	p.u = (l.u & p.U & r.u) | (l.q & p.D & r.p);
    	p.d = (l.d & p.D & r.d) | (l.p & p.U & r.q);
    	p.q = (l.u & p.U & r.q) | (l.q & p.D & r.d);
    	p.p = (l.d & p.D & r.p) | (l.p & p.U & r.u);
    }
    void build(int l,int r,int p)
    {
    	if(l==r) {a[p].U=a[p].D=a[p].u=a[p].d=true; return;}
    	int mid=(l+r)>>1;
    	build(l,mid,ls);
    	build(mid+1,r,rs);
    	pushup(a[p],a[ls],a[rs]);
    }
    void update_r(int x,int val,int opt,int l,int r,int p)
    {
    	int mid=(l+r)>>1;
    	if(x==mid)
    	{
    		if(opt==1) a[p].U=val;
    		else a[p].D=val;
    		pushup(a[p],a[ls],a[rs]);
    		return;
    	}
    	if(x<=mid) update_r(x,val,opt,l,mid,ls);
    	else update_r(x,val,opt,mid+1,r,rs);
    	pushup(a[p],a[ls],a[rs]);
    }
    void update_c(int x,int val,int l,int r,int p)
    {
    	if(l==r) {a[p].l=a[p].r=a[p].p=a[p].q=val; return;}
    	int mid=(l+r)>>1;
    	if(x<=mid) update_c(x,val,l,mid,ls);
    	else update_c(x,val,mid+1,r,rs);
    	pushup(a[p],a[ls],a[rs]);
    }
    Node query(int x,int y,int l,int r,int p)
    {
    	if(x<=l && r<=y) return a[p];
    	int mid=(l+r)>>1;
    	if(y<=mid) return query(x,y,l,mid,ls);
    	else if(x>mid) return query(x,y,mid+1,r,rs);
    	else
    	{
    		Node re=a[p];
    		pushup(re,query(x,y,l,mid,ls),query(x,y,mid+1,r,rs));
    		return re;
    	}
    }
    int main()
    {
    	int c; cin >> c ;
    	build(1,c,1);
    	char s[10];
    	int r1,r2,c1,c2;
    	while(scanf("%s",s) != EOF)
    	{
    		if(s[0] == 'E') break;
    		scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
    		if(c1 > c2) swap(c1,c2),swap(r1,r2);
    		if(s[0] == 'O')
    		{
    			if(r1 == r2) update_r(c1,1,r1,1,c,1);
    			else update_c(c1,1,1,c,1);
    		}
    		if(s[0] == 'C')
    		{
    			if(r1 == r2) update_r(c1,0,r1,1,c,1);
    			else update_c(c1,0,1,c,1);
    		}
    		if(s[0] == 'A')
    		{
    			Node l = query(1,c1,1,c,1),x = query(c1,c2,1,c,1),r = query(c1,c,1,c,1);
    			int ans;
    			// printf("%d
    ",x.u ? 1 : 0);
                // printf("%d
    ",l.r ? 1 : 0);
                // printf("%d
    ",x.p ? 1 : 0);
                // printf("%d
    ",x.q ? 1 : 0);
                // printf("%d
    ",r.l ? 1 : 0);
                // printf("%d
    ",l.r ? 1 : 0);
                // printf("%d
    ",x.d ? 1 : 0);
                // printf("%d
    ",r.l ? 1 : 0);
    			if(r1==1 && r2==1)
    				/* puts("1"), */ans = x.u | (l.r & x.p) | (r.l & x.q) | (l.r & x.d & r.l);
    			if(r1==1 && r2==2)
    				/* puts("2"), */ans = x.q | (l.r & x.d) | (r.l & x.u) | (l.r & x.p & r.l);
    			if(r1==2 && r2==1)
    				/* puts("3"), */ans = x.p | (l.r & x.u) | (r.l & x.d) | (l.r & x.q & r.l);
    			if(r1==2 && r2==2)
    				/* puts("4"), */ans = x.d | (l.r & x.q) | (r.l & x.p) | (l.r & x.u & r.l);
    			puts(ans ? "Y" : "N");
    		}
    	}
    	return 0;
    }
    

    小结:妈的神仙题.....

  • 相关阅读:
    Java并发包中Lock的实现原理
    多线程---再次认识volatile,Synchronize,lock
    共享锁(S锁)和排它锁(X锁)
    Java 7中的TransferQueue 以及 SynchronousQueue
    精巧好用的DelayQueue
    非阻塞同步算法与CAS(Compare and Swap)无锁算法
    彻底理解线索二叉树
    使用import取代require
    子页面iframe跨域执行父页面定义的JS方法
    利用js实现 禁用浏览器后退
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11053958.html
Copyright © 2011-2022 走看看