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

    神仙给我推荐的神仙题

    算是CodeForces413E Maze 2D的加强版吧

    线段树(6)个值维护联通性
    一个矩形(4)个顶点,维护每对顶点的联通性(边和点随便编个号)
    (floyd)更新,讨论合并答案(画个图,其实很简单)

    然后查询时还有(4)种情况
    比如查询(a)的上端到(b)的上端
    第一种:(a)上端->(b)上端
    第二种:(a)上端->(a)下端->(b)上端
    第三种:(a)上端->(b)下端->(b)上端
    第四种:(a)上端->(a)下端->>(b)下端->(b)上端
    在线段树中分别查询(1)(a),(a)(b),(b)(n)的信息然后判断
    注意查询的时候右端点应该减一
    实际上查询的是从(a)的上端入口到(b-1)上端出口(也是(b)的上端入口)
    因此还要特判(a=b)(可以根据连边情况直接判断)

    不知道调试了多久

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define gc c=getchar()
    #define r(x) read(x)
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    
    template<typename T>
    inline void read(T&x){
        x=0;T k=1;char gc;
        while(!isdigit(c)){if(c=='-')k=-1;gc;}
        while(isdigit(c)){x=x*10+c-'0';gc;}x*=k;
    }
    
    const int N=100000;
    
    bool E[N][3];
    
    struct seg{
    	bool f[6];
    	
    	inline const bool& operator [](const int &x)const{
    		return f[x];
    	}
    	
    	inline bool& operator [](const int &x){
    		return f[x];
    	}
    	
    	inline void init(int x){
    		static bool g[4][4];
    		memset(g,0,sizeof(g));
    		if(E[x][0])g[0][1]=g[1][0]=1;
    		if(E[x][1])g[0][2]=g[2][0]=1;
    		if(E[x][2])g[1][3]=g[3][1]=1;
    		if(E[x+1][0])g[2][3]=g[3][2]=1;
    		for(int k=0;k<4;++k){
    			for(int i=0;i<4;++i){
    				for(int j=0;j<4;++j){
    					g[i][j]|=g[i][k]&&g[k][j];
    				}
    			}
    		}
    		f[0]=g[0][1];
    		f[1]=g[0][2];
    		f[2]=g[1][3];
    		f[3]=g[2][3];
    		f[4]=g[0][3];
    		f[5]=g[1][2];
    	}
    	
    	inline friend seg operator + (const seg &a,const seg &b){
    		seg ret;
    		ret[0]=a[0]||(a[1]&&b[0]&&a[2]);
    		ret[1]=(a[1]&&b[1])||(a[4]&&b[5]);
    		ret[2]=(a[2]&&b[2])||(a[5]&&b[4]);
    		ret[3]=b[3]||(b[1]&&a[3]&&b[2]);
    		ret[4]=(a[4]&&b[2])||(a[1]&&b[4]);
    		ret[5]=(a[5]&&b[1])||(a[2]&&b[5]);
    		return ret;
    	}
    }tr[N<<2];
    
    void modify(int rt,int l,int r,int x){
    	if(l==r){
    		tr[rt].init(l);
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid)modify(ls,l,mid,x);
    	else modify(rs,mid+1,r,x);
    	tr[rt]=tr[ls]+tr[rs];
    }
    
    seg query(int rt,int l,int r,int x,int y){
    	if(x<=l&&r<=y)return tr[rt];
    	int mid=(l+r)>>1;
    	if(y<=mid)return query(ls,l,mid,x,y);
    	else if(x>mid)return query(rs,mid+1,r,x,y);
    	else return query(ls,l,mid,x,y)+query(rs,mid+1,r,x,y);
    }
    
    inline int get(bool x,bool y){
    	if(x==0&&y==0)return 1;
    	if(x==0&&y==1)return 4;
    	if(x==1&&y==0)return 5;
    	if(x==1&&y==1)return 2;
    }
    
    int n;
    char s[10];
    
    seg Tmp[2];
    
    inline seg Query(int a,int b){
    	return (a<b)?query(1,1,n,a,b-1):Tmp[E[a][0]];
    }
    
    int main(){
    	r(n);
    	Tmp[0][1]=Tmp[0][2]=1;
    	memset(Tmp[1].f,1,sizeof(Tmp[1].f));
    	while(1){
    		scanf("%s",s);
    		if(s[0]=='E')break;
    		int a,b,c,d;r(a),r(b),r(c),r(d);--a,--c;
    		if(b>d)swap(a,c),swap(b,d);
    		if(s[0]=='A'){
    			seg l=Query(1,b),m=Query(b,d),r=Query(d,n);
    			puts((m[get(a,c)]||((l[3]||m[0])&&m[get(a^1,c)])||((r[0]||m[3])&&m[get(a,c^1)])||((l[3]||m[0])&&(r[0]||m[3])&&m[get(a^1,c^1)]))?"Y":"N");
    		}
    		else {
    			if(b==d)E[b][0]=(s[0]=='O');
    			else E[b][a+1]=(s[0]=='O');
    			if(b==d&&b>1)modify(1,1,n,b-1);
    			modify(1,1,n,b);
    		}
    	}
    }
    
    
  • 相关阅读:
    查看IIS进程W3WP.exe对应网站进程池的PID
    【C#】结对项目开发-电梯调度仿真系统(Bata版)(党云龙、黄为)
    对于敏捷开发的理解!~~~~~~~~(黄为)
    【C】二维数组求最大子数组(基于一维数组的拓展)
    【C#】结对项目开发-电梯调度仿真系统(内部开发者版)(党云龙、黄为)
    【C】课堂结对联系-求整数数组的子数组之和的最大值(党云龙、黄为)
    【C#】结对项目开发-电梯调度需求分析(党云龙、黄为)
    C语言中求整型数组中的最大值!~~~~(黄为,刘佳琪)
    读入文本,找出出现频率最高的10个单词~~~~
    Emmet HTML/CSS代码快速编写神器
  • 原文地址:https://www.cnblogs.com/yicongli/p/9747214.html
Copyright © 2011-2022 走看看