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

    浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1018

    我们把第一行和第二行的城市一起处理,对于每一个区间[(l,r)]的城市,我们需要维护下面六种关系:

    一共六条边,分别用(bool)类型的六个变量来表示这六种联通关系是否成立。

    然后询问两个城市是否联通,也许他们会绕出区间[(l,r)]再绕回来然后联通,所以有四种路径可以走;假设我询问的是一号城市和三号城市,二号城市是一号城市上方/下方的城市,四号城市是三号城市上方/下方的城市,那么这四条路径分别是:

    一号---->三号(红色)

    一号----》二号---->三号(绿色)

    一号---->四号----》三号(蓝色)

    一号----》二号---->四号----》三号(灰色)

    其中>表示在区间内,》表示绕出去,如图所示:

    时间复杂度:(O(nlong))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn=1e5+5;
    
    int n;
    char s[10];
    bool bo[maxn*3];//bo数组里,[1,n-1]存的是第一行的道路,[n,2*n-1]存的是每一列的道路,[2*n,3*n-2]存的是第二行的道路。
    
    int read() {
    	int x=0,f=1;char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return x*f;
    }
    
    struct tree_node {
    	bool a1,a2,a3,a4,a5,a6;
    };
    
    struct segment_tree {
    	tree_node tree[maxn<<2];
    
    	tree_node merge(tree_node f,tree_node g,int mid) {
    		tree_node res;int mid1=mid,mid2=mid+2*n-1;
    		res.a1=(f.a1)|(f.a2&&bo[mid1]&&g.a1&&bo[mid2]&&f.a4);
            //f.a2&&bo[mid1]&&g.a1&&bo[mid2]&&f.a4  1号路径
            //f.a5&&bo[mid2]&&g.a1&&bo[mid1]&&f.a6  2号路径
            //如果2号路径存在那么1号路径必然存在,所以只需要判1号路径即可
    		res.a2=(f.a2&&bo[mid1]&&g.a2)|(f.a5&&bo[mid2]&&g.a6);
    		res.a3=(g.a3)|(g.a2&&bo[mid1]&&f.a3&&bo[mid2]&&g.a4);
    		res.a4=(f.a4&&bo[mid2]&&g.a4)|(f.a6&&bo[mid1]&&g.a5);
    		res.a5=(f.a2&&bo[mid1]&&g.a5)|(f.a5&&bo[mid2]&&g.a4);
    		res.a6=(f.a4&&bo[mid2]&&g.a6)|(f.a6&&bo[mid1]&&g.a2);
    		return res;
    	}
    	
    	void build(int p,int l,int r) {
    		if(l==r) {
    			tree[p].a2=tree[p].a4=1;
    			return;
    		}
    		int mid=(l+r)>>1;
    		build(p<<1,l,mid);
    		build(p<<1|1,mid+1,r);
    	}
    	
    	void change(int p,int l,int r,int L,int R) {
    		if(l==r) {
    			if(L==R) {
    				tree[p].a1^=1;
    				tree[p].a3^=1;
    				tree[p].a5^=1;
    				tree[p].a6^=1;//如果是单点修改那么这四种关系应该改变状态
    			}
    			return;
    		}
    		int mid=(l+r)>>1;
    		if(L<=mid)change(p<<1,l,mid,L,R);
    		else change(p<<1|1,mid+1,r,L,R);
    		tree[p]=merge(tree[p<<1],tree[p<<1|1],mid);		
    	}
    
    	tree_node query(int p,int l,int r,int L,int R) {
    		if(L<=l&&r<=R)return tree[p];
    		int mid=(l+r)>>1;tree_node res;
    		if(R<=mid)res=query(p<<1,l,mid,L,R);
    		else if(L>mid)res=query(p<<1|1,mid+1,r,L,R);
    		else res=merge(query(p<<1,l,mid,L,R),query(p<<1|1,mid+1,r,L,R),mid);
    		return res;
    	}
    }T;
    
    int main() {
    	n=read();T.build(1,1,n);
    	while(~scanf("%s",s+1)) {
    		if(s[1]=='E')break;
    		int x1=read(),y1=read(),x2=read(),y2=read();
    		if(y1>y2)swap(y1,y2),swap(x1,x2);
    		if(s[1]=='O'||s[1]=='C') {
    			if(x1==x2) {
    				int tmp=y1;
    				if(x1==2)tmp+=2*n-1;
    				bo[tmp]^=1;T.change(1,1,n,y1,y2);
    			}
    			else {
    				bo[y1+n-1]^=1;
    				T.change(1,1,n,y1,y2);
    			}
    		}
    		else {
    			bool ans=0;
    			tree_node j=T.query(1,1,n,1,y1);
    			tree_node k=T.query(1,1,n,y1,y2);
    			tree_node l=T.query(1,1,n,y2,n);
    			if(x1==x2) {
    				if(x1==1) {
    					ans|=k.a2;
    					ans|=j.a3&&k.a6;
    					ans|=k.a5&&l.a1;
    					ans|=j.a3&&k.a4&&l.a1;
    				}
    				else {
    					ans|=k.a4;
    					ans|=j.a3&&k.a5;
    					ans|=k.a6&&l.a1;
    					ans|=j.a3&&k.a2&&l.a1;
    				}
    			}
    			else {
    				if(x1==1) {
    					ans|=k.a5;
    					ans|=j.a3&&k.a4;
    					ans|=k.a2&&l.a1;
    					ans|=j.a3&&k.a6&&l.a1;
    				}
    				else {
    					ans|=k.a6;
    					ans|=j.a3&&k.a2;
    					ans|=k.a4&&l.a1;
    					ans|=j.a3&&k.a5&&l.a1;
    				}
    			}//对于询问的两个点的位置一共有四种不同的关系,分别分情况讨论
    			if(ans)puts("Y");
    			else puts("N");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    java实现第七届蓝桥杯阶乘位数
    java实现第七届蓝桥杯圆圈舞
    java实现第七届蓝桥杯圆圈舞
    java实现第七届蓝桥杯圆圈舞
    java实现第七届蓝桥杯圆圈舞
    java实现第七届蓝桥杯圆圈舞
    java实现第七届蓝桥杯打靶
    java实现第七届蓝桥杯打靶
    Mysql 查询一天中,每个小时数据的数量
    mysql 获取昨天日期、今天日期、明天日期以及前一个小时和后一个小时的时间
  • 原文地址:https://www.cnblogs.com/AKMer/p/9956256.html
Copyright © 2011-2022 走看看