• [BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】


    题目链接:BZOJ - 1018

    题目分析

    这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题..

    这道题是线段树维护联通性的经典模型。

    我们线段树的一个节点表示一个区间的联通性,有 6 个 bool 值,表示这个区间的 4 个角上的点之间的联通性。

    然后用两个子区间的联通性和两个子区间之间的连边情况合并出整个区间的联通性。

    修改某条边时,先在边的数组中修改,然后从这条边所在的点的线段树叶子开始向上 Update 。

    询问两点之间的联通性时,假如它们的列分别是 y1, y2, 那么我们要求出 [1, y1] [y1, y2] [y2, n] 的联通性。

    然后用这三个联通性组合起来手动枚举各种情况判断两个点是否联通。

    因为分别处于 y1, y2 的两个点,之间可能不只是通过 [y1, y2] 之间的边联通,而是需要用到两侧的边连接起来。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    inline int gmin(int a, int b) {return a < b ? a : b;}
    inline int gmax(int a, int b) {return a > b ? a : b;}
    
    const int MaxN = 100000 + 5;
    
    int n;
    
    char Str[15];
    
    bool A[MaxN][3];
    
    struct ES
    {
    	bool a1, a2, b1, b2, c1, c2;
    } T[MaxN * 4]; 
    
    inline ES Plus(ES e1, ES e2, int m)
    {
    	ES ret;
    	ret.a1 = e1.a1 || (e1.b1 && e1.b2 && A[m][1] && A[m][2] && e2.a1);
    	ret.a2 = e2.a2 || (e2.b1 && e2.b2 && A[m][1] && A[m][2] && e1.a2);
    	ret.b1 = (e1.b1 && A[m][1] && e2.b1) || (e1.c1 && A[m][2] && e2.c2);
    	ret.b2 = (e1.b2 && A[m][2] && e2.b2) || (e1.c2 && A[m][1] && e2.c1);
    	ret.c1 = (e1.b1 && A[m][1] && e2.c1) || (e1.c1 && A[m][2] && e2.b2);
    	ret.c2 = (e1.b2 && A[m][2] && e2.c2) || (e1.c2 && A[m][1] && e2.b1);
    	return ret;
    }
    
    void Build(int x, int s, int t)
    {
    	if (s == t)
    	{
    		T[x].a1 = T[x].a2 = T[x].c1 = T[x].c2 = false;
    		T[x].b1 = T[x].b2 = true;
    		return;
    	}
    	int m = (s + t) >> 1;
    	Build(x << 1, s, m);
    	Build(x << 1 | 1, m + 1, t);
    	T[x] = Plus(T[x << 1], T[x << 1 | 1], m);
    }
    
    void Modify(int x, int s, int t, int Pos)
    {
    	if (s == t)
    	{
    		T[x].a1 = T[x].a2 = T[x].c1 = T[x].c2 = A[Pos][0];
    		T[x].b1 = T[x].b2 = true;
    		return;
    	}
    	int m = (s + t) >> 1;
    	if (Pos <= m) Modify(x << 1, s, m, Pos);
    	else Modify(x << 1 | 1, m + 1, t, Pos);
    	T[x] = Plus(T[x << 1], T[x << 1 | 1], m);
    }
    
    ES Get(int x, int s, int t, int l, int r)
    {
    	if (l <= s && r >= t) return T[x];
    	ES ret;
    	int m = (s + t) >> 1;
    	if (r <= m) ret = Get(x << 1, s, m, l, r);
    	else if (l >= m + 1) ret = Get(x << 1 | 1, m + 1, t, l, r);
    	else ret = Plus(Get(x << 1, s, m, l, r), Get(x << 1 | 1, m + 1, t, l, r), m);
    	return ret;
    }
    
    int main()
    {
    	scanf("%d", &n);
    	int x, y, xx, yy;
    	bool f, Ans;
    	ES El, Ex, Er;
    	Build(1, 1, n);
    	while (true)
    	{
    		scanf("%s", Str);
    		if (strcmp(Str, "Exit") == 0) break;
    		scanf("%d%d%d%d", &x, &y, &xx, &yy);
    		if (strcmp(Str, "Ask") == 0)
    		{
    			if (y > yy) 
    			{
    				swap(x, xx);
    				swap(y, yy);
    			}
    			El = Get(1, 1, n, 1, y);
    			Ex = Get(1, 1, n, y, yy);
    			Er = Get(1, 1, n, yy, n);
    			if (x == xx)
    			{
    				if (x == 1) 
    					Ans = Ex.b1 || 
    					(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.c2) || 
    					(A[yy][1] && A[yy][2] && Er.a1 && Ex.c1) || 
    					(A[y - 1][1] && A[y - 1][2] && El.a2 && A[yy][1] && A[yy][2] && Er.a1 && Ex.b2);
    				else 
    					Ans = Ex.b2 || 
    					(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.c1) || 
    					(A[yy][1] && A[yy][2] && Er.a1 && Ex.c2) || 
    					(A[y - 1][1] && A[y - 1][2] && El.a2 && A[yy][1] && A[yy][2] && Er.a1 && Ex.b1);
    			}
    			else
    			{
    				if (x < xx)
    					Ans = Ex.c1 || 
    					(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.b2) || 
    					(Ex.b1 && A[yy][1] && A[yy][2] && Er.a1);
    				else 
    					Ans = Ex.c2 || 
    					(A[y - 1][1] && A[y - 1][2] && El.a2 && Ex.b1) || 
    					(Ex.b2 && A[yy][1] && A[yy][2] && Er.a1);
    			}
    			if (Ans) printf("Y
    ");
    			else printf("N
    ");	
    		}
    		else
    		{
    			if (strcmp(Str, "Open") == 0) f = true;
    			else f = false;
    			if (x == xx) 
    			{	
    				A[gmin(y, yy)][x] = f;
    				Modify(1, 1, n, gmin(y, yy));
    			}
    			else
    			{
    				A[y][0] = f;
    				Modify(1, 1, n, y);
    			}
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    where和having的区别
    lnmp环境安装
    Elasticsearch 日常维护命令
    Haproxy基础知识
    LVM常规操作记录梳理(扩容/缩容/快照等)
    Centos7下ELK+Redis日志分析平台的集群环境部署记录
    CentOS7.2下安装php加速软件Xcache
    ELK实时日志分析平台环境部署
    Docker容器时间跟主机时间保持同步的操作记录
    ELK基础架构解析
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4436363.html
Copyright © 2020-2023  润新知