zoukankan      html  css  js  c++  java
  • [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;
    }
    

      

  • 相关阅读:
    想做一个显示全国火车运行图的网站(3) 位置的计算
    directX9SDK中提取的9个DLL文件
    基于google map api开发web和google earth的KML地标插件
    C#winform使用XML绑定toolStripMenuItem生成菜单
    visual studio主题 代码样式
    Oracle ADF初体验
    OBIEE + OAS集群配置 Part 1
    Oracle创建外部表
    Oracle Data Integrator改变字体大小方法
    无题
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4436363.html
Copyright © 2011-2022 走看看