这题需要维护连通性,看到有连接删除,很容易直接就想LCT了。然而这题点数20w操作10w,LCT卡常估计过不去。看到这个东西只有两行,考虑能否用魔改后的线性数据结构去维护。我想到了线段树。

考虑如果两个点相连,能有几种情况。有一种是两个点直接经过中间的路径相连,这个满足合并性,很容易维护。然后就是某一个点(或两个点)从两边绕了一下,由上到下或由下到上,然后走中间了路径相连的情况。

(借用官方的一张图)

对于第二种情况,考虑它应该是是什么样子的。注意这张图总共就两行,那么这个东西一定是从上面一行走横着的边到某一个位置,走一条竖着的边,然后再到下面连续走横着的边。

所以,我们对于某一个位置能否到达其对应位置,只需要维护其横向能到达的最远位置,以及这两个位置之间有没有纵向边即可。

确定位置只需要维护横向连通性,然后线段树二分即可。

横向连通性满足合并性,总向边可以用数量求和,均可以用线段树维护。

于是此题得解。

关于实现,我们定义每个区间保存一个Node,其中f[0/1][0/1]表示区间左边的上、下能否到区间右边的上下(0上1下),维护linked[0/1]表示区间(0上1下)是否左右全部联通,同时维护sum表示这个区间纵向边数量的和。

对于每一个位置,维护ver表示是否有纵向边,hor[0/1]表示从位置i有没有到位置i+1的横向边(0上1下)。

合并的话节点直接用左右状态判,和很容易转移。

查询位置的线段树二分,无非就是先向上走再向下走,自行脑补一发即可(不会看代码)。

最终判定的时候用了一下状压,仅能判定上面的点用1,仅能判定下面用2,如果上下联通,则均可判定,用3来表示。

最后上代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define debug cout
  6 using namespace std;
  7 const int maxn=1e5+1e2;
  8
  9 int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],fa[maxn<<3];
 10 int linked[maxn<<3][2],ver[maxn],hor[maxn][2];
 11 int sum[maxn<<3];
 12
 13 struct Node {
 14     int f[2][2];
 15     int* operator [] (const int &x) {
 16         return f[x];
 17     }
 18     Node() {
 19         memset(f,0,sizeof(f));
 20     }
 21 }ns[maxn<<3];
 22 int n,m,cnt;
 23
 24 inline Node merge(int* h,Node a,Node b) {
 25     Node ret;
 26     ret.f[0][0] = ( a[0][0]&h[0]&b[0][0] ) | ( a[0][1]&h[1]&b[1][0] );
 27     ret.f[1][1] = ( a[1][1]&h[1]&b[1][1] ) | ( a[1][0]&h[0]&b[0][1] );
 28     ret.f[0][1] = ( a[0][0]&h[0]&b[0][1] ) | ( a[0][1]&h[1]&b[1][1] );
 29     ret.f[1][0] = ( a[1][1]&h[1]&b[1][0] ) | ( a[1][0]&h[0]&b[0][0] );
 30     return ret;
 31 }
 32
 33 inline void build(int pos,int ll,int rr) {
 34     l[pos] = ll , r[pos] = rr;
 35     if( ll == rr ) {
 36         ns[pos][0][0] = ns[pos][1][1] = 1;
 37         linked[pos][0] = linked[pos][1] = 1;
 38         return;
 39     }
 40     const int mid = ( ll + rr ) >> 1;
 41     build(lson[pos]=++cnt,ll,mid);
 42     build(rson[pos]=++cnt,mid+1,rr);
 43     fa[lson[pos]] = fa[rson[pos]] = pos;
 44 }
 45 inline void update_ver(int pos,int tar,int sta) {
 46     if( tar < l[pos] || r[pos] < tar )
 47         return;
 48     if( l[pos] == r[pos] ) {
 49         sum[pos] = ver[tar] = sta;
 50         ns[pos][0][1] = ns[pos][1][0] = sta;
 51         return;
 52     }
 53     const int mid = ( l[pos] + r[pos] ) >> 1;
 54     update_ver(lson[pos],tar,sta);
 55     update_ver(rson[pos],tar,sta);
 56     ns[pos] = merge(hor[mid],ns[lson[pos]],ns[rson[pos]]);
 57     sum[pos] = sum[lson[pos]] + sum[rson[pos]]; // remember this
 58 }
 59 inline void update_hor(int pos,int tar,int at,int sta) {
 60     if( tar < l[pos] || r[pos] < tar )
 61         return;
 62     if( l[pos] == r[pos] ) {
 63         hor[tar][at] = sta;
 64         return;
 65     }
 66     const int mid = ( l[pos] + r[pos] ) >> 1;
 67     update_hor(lson[pos],tar,at,sta);
 68     update_hor(rson[pos],tar,at,sta);
 69     ns[pos] = merge(hor[mid],ns[lson[pos]],ns[rson[pos]]);
 70     linked[pos][0] = linked[lson[pos]][0] & hor[mid][0] & linked[rson[pos]][0],
 71     linked[pos][1] = linked[lson[pos]][1] & hor[mid][1] & linked[rson[pos]][1];
 72 }
 73 inline Node querymid(int pos,int ll,int rr) {
 74     if( !pos )
 75         exit(0);
 76     if( ll <= l[pos] && r[pos] <= rr )
 77         return ns[pos];
 78     const int mid = ( l[pos] + r[pos] ) >> 1;
 79     if( rr <= mid )
 80         return querymid(lson[pos],ll,rr);
 81     if( ll > mid )
 82         return querymid(rson[pos],ll,rr);
 83     return merge(hor[mid],querymid(lson[pos],ll,rr),querymid(rson[pos],ll,rr));
 84 }
 85 inline int queryver(int pos,int ll,int rr) {
 86     if( rr < l[pos] || r[pos] < ll )
 87         return 0;
 88     if( ll <= l[pos] && r[pos] <= rr )
 89         return sum[pos];
 90     return queryver(lson[pos],ll,rr) + queryver(rson[pos],ll,rr);
 91 }
 92 inline int downleft(int pos,int at) {
 93     if( l[pos] == r[pos] )
 94         return l[pos];
 95     const int mid = ( l[pos] + r[pos] ) >> 1;
 96     if( hor[mid][at] && linked[rson[pos]][at] )
 97         return downleft(lson[pos],at);
 98     return downleft(rson[pos],at);
 99 }
100 inline int leftup(int pos,int at) {
101     if( pos == 1 )
102         return 1;
103     if( pos == lson[fa[pos]] )
104         return leftup(fa[pos],at);
105     const int fmid = l[pos] - 1;
106     if( hor[fmid][at] ) {
107         if( linked[lson[fa[pos]]][at] )
108             return leftup(fa[pos],at);
109         return downleft(lson[fa[pos]],at);
110     }
111     return l[pos];
112 }
113 inline int downright(int pos,int at) {
114     if( l[pos] == r[pos] )
115         return r[pos];
116     const int mid = ( l[pos] + r[pos] ) >> 1;
117     if( hor[mid][at] && linked[lson[pos]][at] )
118         return downright(rson[pos],at);
119     return downright(lson[pos],at);
120 }
121 inline int rightup(int pos,int at) {
122     if( pos == 1 )
123         return n;
124     if( pos == rson[fa[pos]] )
125         return rightup(fa[pos],at);
126     const int fmid = r[pos];
127     if( hor[fmid][at] ) {
128         if( linked[rson[fa[pos]]][at] )
129             return rightup(fa[pos],at);
130         return downright(rson[fa[pos]],at);
131     }
132     return r[pos];
133 }
134 inline int findpos(int pos,int tar) {
135     while( l[pos] != r[pos] ) {
136         const int mid = ( l[pos] + r[pos] ) >> 1;
137         if( tar <= mid )
138             pos = lson[pos];
139         else
140             pos = rson[pos];
141     }
142     return pos;
143 }
144
145 inline void solve_case(int x,int y,int xx,int yy) {
146     int sta = y , stb = yy , ans = 0;
147     const int mostl = max( leftup(findpos(1,x),0) , leftup(findpos(1,x),1) );
148     const int mostr = min( rightup(findpos(1,xx),0) , rightup(findpos(1,xx),1) );
149     if( queryver(1,mostl,x) )
150         sta = 3;
151     if( queryver(1,xx,mostr) )
152         stb = 3;
153     Node md = querymid(1,x,xx);
154     for(int i=0;i<2;i++)
155         for(int j=0;j<2;j++)
156             if( ( sta & (1<<i) ) && ( stb & (1<<j) ) )
157                 ans |= md[i][j];
158     puts(ans?"Y":"N");
159 }
160
161 char com[10];
162 int x,y,xx,yy;
163
164 inline void explain() {
165     int sta = *com == 'O';
166     if( y == yy )
167         update_hor(1,x,y-1,sta);
168     else if( x == xx ) {
169         update_ver(1,x,sta);
170     }
171 }
172
173 int main() {
174     scanf("%d",&n);
175     build(cnt=1,1,n);
176     int cc = 0;
177     while( scanf("%s",com) == 1 && *com != 'E' ) {
178         scanf("%d%d%d%d",&y,&x,&yy,&xx);
179         if( x > xx )
180             swap(x,xx) , swap(y,yy);
181         if( *com == 'A' )
182             solve_case(x,y,xx,yy);
183         else
184             explain();
185     }
186
187     return 0;
188
189 }

转载于:https://www.cnblogs.com/Cmd2001/p/8127620.html

Bzoj1018[SHOI2008]堵塞的交通traffic(线段树)相关推荐

  1. BZOJ[1018][SHOI2008]堵塞的交通traffic 线段树

    传送门ber~ 哇这个线段树好神啊!! 用线段树维护图连通性,每个节点开个二维数组 ai,j a i , j a_{i,j}表示这个区间最左面的第 i i i行能不能走到最右面的第j" ro ...

  2. BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)

    传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...

  3. BZOJ1018 | SHOI2008-堵塞的交通traffic——线段树维护区间连通性+细节

    [题目描述] BZOJ1018 | SHOI2008-堵塞的交通traffic 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可 以被看成是一个2行C列 ...

  4. BZOJ1018 [SHOI2008] 堵塞的交通traffic

    @(BZOJ)[线段树] Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可 以被看成是一个\(2\)行\(C\)列的矩形网格,网 ...

  5. bzoj1018[SHOI2008]堵塞的交通traffic

    题目链接:bzoj1018 题目大意: 一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个城市和3C-2条道路. 交通信息可以分为以下几种格式: Close ...

  6. Bzoj1018 [SHOI2008]堵塞的交通traffic

    Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 3458  Solved: 1158 Description 有一天,由于某种穿越现象作用,你来到了传说 ...

  7. BZOJ1018: [SHOI2008]堵塞的交通traffic

    线段树维护每一块左上到左下.右上到右下.左上到右上.左下到右下.左上到右下.左下到右上的联通情况. upd:可以直接用3082的方法搞,能过. #include<bits/stdc++.h> ...

  8. BZOJ 1018: [SHOI2008]堵塞的交通traffic

    二次联通门 : BZOJ 1018: [SHOI2008]堵塞的交通traffic /*BZOJ 1018: [SHOI2008]堵塞的交通traffic麻麻这题玩我这题简直消磨人的意志写了一天了写一 ...

  9. [BZOJ1018]SHOI2008堵塞的交通|线段树

    好神的线段树题,以前只会维护区间什么数值信息的,竟然还可以维护联通性,好题啊,涨姿势了.. 由于只有两行嘛,要保证线段树节点有可加性,我们维护六个信息,分别是右上到右下,右上到左上,右上到左下,右下到 ...

最新文章

  1. 用InstallShield 打包工具 打 Win32 程序 (depends.exe 用看程序都依赖了哪些dll)
  2. 一部论述修养人生处世出世的集录_读《菜根谭》,人生本是修心的过程
  3. ux和ui_他们说,以UX / UI设计师的身份加入一家初创公司。 他们说,这会很有趣。
  4. 让人吐血的文章,要被气死了
  5. Linux系统(Centos)下安装nodejs并配置环境
  6. 2d游戏引擎_8年,从2D到3D,我的学习之路
  7. 平均数和均值一样吗_求平均数!
  8. 关于collectionView的一些内容
  9. My97DatePickerBeta日期控件乱码问题解决方案
  10. Android中加载ETC2压缩格式(PKM后缀)纹理
  11. Solidworks常用插件介绍
  12. war压缩命令_宝塔面板linux版解压WAR文件时,如何解压的三种方法介绍
  13. IE浏览器怎么设置兼容性 添加兼容站点方法
  14. Decal Buffer相关
  15. 2019云计算机峰会,计算机学院师生参加“2019华为云城市峰会”
  16. python实现单机斗地主手机版下载_单机斗地主(单机版)无需网络下载
  17. python字符串的定界符可以是_Python中,字符串不能用以下哪个符号作为定界符(): \|'|'''|;...
  18. SOI七层模型和TCP/IP五层协议:
  19. 使用lodop设置导出表格的数据格式
  20. 对话 | 港科大教授权龙:为什么三维重建才是计算机视觉的灵魂?

热门文章

  1. 亚马逊云科技以用户为中心,持续丰富安全服务和解决方案
  2. CSS实现间距相同 首尾无边距处理
  3. html单选框怎么提交数据库,HTML复选框和单选框 checkbox和radio事件介绍
  4. VUE实现一个简单的登录加密和后端(JAVA)解密功能
  5. 魔百盒CM101S-2/咪咕MG100-支持多种无线-Hi3798MV100-免拆机卡刷固件包
  6. VideoScribe卡死解决方案
  7. redis学习笔记(九)RDB
  8. TeXstudio——入门
  9. java报错意外的类型_Java意外类型错误
  10. 怀胎的历程及注意事项