线段树的每个叶子节点存一列。

每个节点维护六个域,分别是左上左下、左上右上、左上右下、左下右上、左下右下、右上右下在区间内部的连通性,不考虑绕出去的情况。

初始每个叶子的左上左下、右上右下是连通的。

每次修改纵列时,直接去线段树里修改。

每次修改横行时,将其左右两列全都pushup一遍。

具体怎么维护,并不难,请自行思考。

每次询问时,提取出来[1,l-1],[l,r],[r+1,n]的连通性,然后讨论是否绕出来的情况。

不推荐使用循环维护,人工讨论反而更加方便。

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 100001
int n;
bool heng[2][N];/*heng(i,j)±íʾ(i,j)ºÍ(i+1,j)Ö®¼äÊÇ·ñÓбß*/
bool zong[N];/*zong(i)±íʾ(0,i)ºÍ(1,i)Ö®¼äÊÇ·ñÓбß*/
struct Node{bool zszx,zsys,zsyx,zxys,zxyx,ysyx;}T[N<<2];
/*!!!ÐèÒªµ¥¶ÀÌÖÂÛµ¥¸ö×ÝÁÐºÍÆäËûµÄºÏ²¢µÄÇé¿ö!!!...ºÃ°ÉÆäʵ²»ÓÃ...³õʼʱÿ¸ö×ÝÁеÄzsys,zxyx=1*/
inline void pushup(Node &rt,const Node &ls,const Node &rs,const int &r1)
{
if(ls.zszx) rt.zszx=1;//zszx
else if(ls.zsys && rs.zszx && ls.zxyx && heng[0][r1] && heng[1][r1]) rt.zszx=1;
else rt.zszx=0;
if(rs.ysyx) rt.ysyx=1;//ysyx
else if(rs.zsys && ls.ysyx && rs.zxyx && heng[0][r1] && heng[1][r1]) rt.ysyx=1;
else rt.ysyx=0;
if(ls.zsys && rs.zsys && heng[0][r1]) rt.zsys=1;//zsys
else if(ls.zsyx && rs.zxys && heng[1][r1]) rt.zsys=1;
else rt.zsys=0;
if(ls.zsys && rs.zsyx && heng[0][r1]) rt.zsyx=1;//zsyx
else if(ls.zsyx && rs.zxyx && heng[1][r1]) rt.zsyx=1;
else rt.zsyx=0;
if(ls.zxys && rs.zsys && heng[0][r1]) rt.zxys=1;//zxys
else if(ls.zxyx && rs.zxys && heng[1][r1]) rt.zxys=1;
else rt.zxys=0;
if(ls.zxys && rs.zsyx && heng[0][r1]) rt.zxyx=1;//zxyx
else if(ls.zxyx && rs.zxyx && heng[1][r1]) rt.zxyx=1;
else rt.zxyx=0;
}
void update(int p,bool v,int rt,int l,int r)/*µ¥×ÝÁÐÐÞ¸Ä*/
{
if(l==r)
{
zong[p]=v;
T[rt].zszx=T[rt].zsyx=T[rt].zxys=T[rt].ysyx=v;
return;
}
int m=(l+r>>1);
if(p<=m) update(p,v,rt<<1,l,m);
else update(p,v,rt<<1|1,m+1,r);
pushup(T[rt],T[rt<<1],T[rt<<1|1],m);
}
void update(int p,int rt,int l,int r)/*ÓÉÓÚÅԱߵĺáÐнøÐÐÁËÐ޸Ķø½øÐеĵ¥×ÝÁиüÐÂ*/
{
if(l==r) return;
int m=(l+r>>1);
if(p<=m) update(p,rt<<1,l,m);
else update(p,rt<<1|1,m+1,r);
pushup(T[rt],T[rt<<1],T[rt<<1|1],m);
}
Node query(int ql,int qr,int rt,int l,int r)
{
if(ql<=l && r<=qr) return T[rt];
int m=(l+r>>1);
if(ql<=m && m<qr)
{
Node res;
pushup(res,query(ql,qr,rt<<1,l,m),query(ql,qr,rt<<1|1,m+1,r),m);
return res;
}
else if(ql<=m) return query(ql,qr,rt<<1,l,m);
else return query(ql,qr,rt<<1|1,m+1,r);
}
inline bool query(const bool &x1,const int &y1,const bool &x2,const int &y2)
{
Node M=query(y1,y2,1,1,n),L,R;
if(y1!=1) L=query(1,y1-1,1,1,n);
if(y2!=n) R=query(y2+1,n,1,1,n);
if(x1 && x2)
{
if(M.zxyx) return 1;
if(y1!=1) if(L.ysyx && M.zsyx && heng[0][y1-1] && heng[1][y1-1]) return 1;
if(y2!=n) if(R.zszx && M.zxys && heng[0][y2] && heng[1][y2]) return 1;
if(y1!=1 && y2!=n) if(L.ysyx && heng[0][y1-1] && heng[1][y1-1]
&& R.zszx && heng[0][y2] && heng[1][y2] && M.zsys)
return 1;
return 0;
}
else if(x1)
{
if(M.zxys) return 1;
if(y1!=1) if(L.ysyx && M.zsys && heng[0][y1-1] && heng[1][y1-1]) return 1;
if(y2!=n) if(R.zszx && M.zxyx && heng[0][y2] && heng[1][y2]) return 1;
if(y1!=1 && y2!=n) if(L.ysyx && heng[0][y1-1] && heng[1][y1-1]
&& R.zszx && heng[0][y2] && heng[1][y2] && M.zsyx)
return 1;
return 0;
}
else if(x2)
{
if(M.zsyx) return 1;
if(y1!=1) if(L.ysyx && M.zxyx && heng[0][y1-1] && heng[1][y1-1]) return 1;
if(y2!=n) if(R.zszx && M.zsys && heng[0][y2] && heng[1][y2]) return 1;
if(y1!=1 && y2!=n) if(L.ysyx && heng[0][y1-1] && heng[1][y1-1]
&& R.zszx && heng[0][y2] && heng[1][y2] && M.zxys)
return 1;
return 0;
}
else
{
if(M.zsys) return 1;
if(y1!=1) if(L.ysyx && M.zxys && heng[0][y1-1] && heng[1][y1-1]) return 1;
if(y2!=n) if(R.zszx && M.zsyx && heng[0][y2] && heng[1][y2]) return 1;
if(y1!=1 && y2!=n) if(L.ysyx && heng[0][y1-1] && heng[1][y1-1]
&& R.zszx && heng[0][y2] && heng[1][y2] && M.zxyx)
return 1;
return 0;
}
}
int main()
{
// freopen("bzoj1018.in","r",stdin);
char op[7];
int x1,x2,y1,y2;
scanf("%d",&n);
for(int i=1;i<=(n<<2);++i)
T[i].zsys=T[i].zxyx=1;
while(1)
{
scanf("%s",op);
if(op[0]=='E') break;
else if(op[0]=='O')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(y1==y2) update(y1,1,1,1,n);
else
{
if(y1>y2) swap(y1,y2);
heng[x1-1][y1]=1;
update(y1,1,1,n);
update(y2,1,1,n);
}
}
else if(op[0]=='C')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(y1==y2) update(y1,0,1,1,n);
else
{
if(y1>y2) swap(y1,y2);
heng[x1-1][y1]=0;
update(y1,1,1,n);
update(y2,1,1,n);
}
}
else
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(y1>y2)
{
swap(x1,x2);
swap(y1,y2);
}
puts(query(x1-1,y1,x2-1,y2) ? "Y" : "N");
}
}
return 0;
}

【线段树】bzoj1018 [SHOI2008]堵塞的交通traffic的更多相关文章

  1. [BZOJ1018][SHOI2008]堵塞的交通traffic 线段树维护连通性

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 3795  Solved: 1253 [Sub ...

  2. bzoj千题计划108:bzoj1018: [SHOI2008]堵塞的交通traffic

    http://www.lydsy.com/JudgeOnline/problem.php?id=1018 关键点在于只有两行 所以一个2*m矩形连通情况只有6种 编号即对应代码中的a数组 线段树维护 ...

  3. 【离线 撤销并查集 线段树分治】bzoj1018: [SHOI2008]堵塞的交通traffic

    本题可化成更一般的问题:离线动态图询问连通性 当然可以利用它的特殊性质,采用在线线段树维护一些标记的方法 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常 ...

  4. Bzoj1018[SHOI2008]堵塞的交通traffic(线段树)

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

  5. bzoj1018[SHOI2008]堵塞的交通traffic——线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1018 巧妙的线段树.维护矩阵四个角的连通性. 考虑两个点连通的可能路径分成3部分:两点左边. ...

  6. [BZOJ1018][SHOI2008]堵塞的交通traffic 时间分治线段树

    题面 介绍一种比较慢的但是好想的做法. 网上漫天的线段树维护联通性,然后想起来费很大周折也很麻烦.我的做法也是要用线段树的,不过用法完全不同. 这个东西叫做时间分治线段树. 首先我们建一个\(1..m ...

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

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  8. [bzoj1018][SHOI2008]堵塞的交通traffic_线段树

    bzoj-1018 SHOI-2008 堵塞的交通traffic 参考博客:https://www.cnblogs.com/MashiroSky/p/5973686.html 题目大意:有一天,由于某 ...

  9. 【BZOJ1018】[SHOI2008]堵塞的交通traffic 线段树

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

随机推荐

  1. [转]Android音频底层调试-基于tinyalsa

    http://blog.csdn.net/kangear/article/details/38139669 [-] 编译tinyalsa配套工具 查看当前系统的声卡 tinymix查看混响器 使用ti ...

  2. Android应用自动更新功能的代码实现

    由于Android项目开源所致,市面上出现了N多安卓软件市场.为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量.因此我们有必 ...

  3. LeetCode 445 Add Two Numbers II

    445-Add Two Numbers II You are given two linked lists representing two non-negative numbers. The mos ...

  4. 【Android端 APP 启动时长获取】启动时长获取方案及具体实施

    一.什么是启动时长? 1.启动时长一般包括三种场景,分别是:新装包的首次启动时长,冷启动时长.热启动时长 冷启动 和 热启动 : (1)冷启动:当启动应用时,后台没有该程序的进程,此时启动的话系统会分 ...

  5. JavaScript内置对象之数组

    一.JavaScript对象之数组 1.创建数组的方式 (1)使用Array构造函数 语法:new Array() 小括号()说明: -预先知道数组要保存的项目数量 -向Array构造函数中传递数组应 ...

  6. hdu 1398 Square Coins (母函数)

    Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  7. SpringMVC结合easyUI中datagird实现分页

    SpringMVC结合easyUI中datagird实现分页 DataGrid以表格形式展示数据,并提供了丰富的选择.排序.分组和编辑数据的功能支持.轻量级,单元格合并.多列标题.冻结列和页脚只是其中 ...

  8. Multi-armed Bandit Problem与增强学习的联系

    选自<Reinforcement Learning: An Introduction>, version 2, 2016, Chapter2 https://webdocs.cs.ualb ...

  9. HTTP 协议缓存

    http 缓存分为客户端缓存和服务端缓存 1. 客户端缓存 客户端缓存指的是浏览器缓存, 浏览器缓存是最快的缓存, 因为它直接从本地获取(但有可能需要发送一个请求), 它的优势是可以减少网络流量, 加 ...

  10. yum源配置与使用

    一.yum 简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发行版的 ...