P4246 [SHOI2008]堵塞的交通

题意

题目描述

有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可以被看成是一个\(2\)行\(C\)列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有\(2C\)个城市和\(3C-2\)条道路。

小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:

  • Close r1 c1 r2 c2:相邻的两座城市\((r_1, c_1)\)和\((r_2, c_2)\)之间的道路被堵塞了;
  • Open r1 c1 r2 c2:相邻的两座城市\((r_1, c_1)\)和\((r_2, c_2)\)之间的道路被疏通了;
  • Ask r1 c1 r2 c2:询问城市\((r_1, c_1)\)和\((r_2, c_2)\)是否连通。如果存在一条路径使得这两条城市连通,则返回Y,否则返回N

注:\(r_i\)表示行数,\(c_i\)表示列数, \(1\leq r_i\leq 2,1\leq c_i\leq C\)。

输入输出格式

输入格式:

第一行只有一个整数\(C\),表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行Exit作为结束。我们假设在一开始所有的道路都是堵塞的。我们保证\(C\)小于等于\(100000\),信息条数小于等于\(100000\)。

输出格式:

对于每个查询,输出一个YN

输入输出样例

输入样例#1:

2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit

输出样例#1:

Y
N

说明

数据范围:

对于\(100\%\)的数据,\(1\leq C\leq 100000,1\leq \text{信息条数}\leq 100000\)。

思路

什么**线段树。 --Mercury

用线段树来写,每个结点维护区间\([l,r]\)的连通性。维护时记录六个值:

  1. \(ldrd(left-down\ to\ right-down)\)
  2. \(luru(left-up\ to\ right-up)\)
  3. \(luld(left-up\ to\ left-down)\)
  4. \(rurd(right-up\ to\ right-down)\)
  5. \(lurd(left-up\ to\ right-down)\)
  6. \(ldru(left-down\ to\ right-up)\)

合并过程其实就是大力模拟的过程,考虑所有的路的经过情况。详见代码的两个update函数。

修改的时候要分类讨论,横线的变化与竖线的变化是不同的情况。

查询的时候要注意,两点可能绕外面的路互相到达,所以还是要大力模拟,考虑绕路和不绕路的情况。

代码的变量名还是比较清楚的,所以就详见代码吧 (才不是我懒得写) 。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int n;
int ru[MAXN],rd[MAXN];
struct SegmentTree
{
int l,r;
bool ldrd,luru,luld,rurd,lurd,ldru;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define ldrd(x) tree[x].ldrd
#define luru(x) tree[x].luru
#define luld(x) tree[x].luld
#define rurd(x) tree[x].rurd
#define lurd(x) tree[x].lurd
#define ldru(x) tree[x].ldru
}tree[MAXN<<2];
int read()
{
int re=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
char readc()
{
char ch=getchar();
while(!isalpha(ch)) ch=getchar();
return ch;
}
void update(int p)
{
l(p)=l(p<<1),r(p)=r(p<<1|1);
ldrd(p)=(ldrd(p<<1)&&rd[r(p<<1)]&&ldrd(p<<1|1))||(ldru(p<<1)&&ru[r(p<<1)]&&lurd(p<<1|1));
luru(p)=(luru(p<<1)&&ru[r(p<<1)]&&luru(p<<1|1))||(lurd(p<<1)&&rd[r(p<<1)]&&ldru(p<<1|1));
luld(p)=luld(p<<1)||(luru(p<<1)&&ru[r(p<<1)]&&luld(p<<1|1)&&rd[r(p<<1)]&&ldrd(p<<1));
rurd(p)=rurd(p<<1|1)||(luru(p<<1|1)&&ru[r(p<<1)]&&rurd(p<<1)&&rd[r(p<<1)]&&ldrd(p<<1|1));
lurd(p)=(luru(p<<1)&&ru[r(p<<1)]&&lurd(p<<1|1))||(lurd(p<<1)&&rd[r(p<<1)]&&ldrd(p<<1|1));
ldru(p)=(ldrd(p<<1)&&rd[r(p<<1)]&&ldru(p<<1|1))||(ldru(p<<1)&&ru[r(p<<1)]&&luru(p<<1|1));
}
void update(SegmentTree &re,SegmentTree x,SegmentTree y)
{
re.l=x.l,re.r=y.r;
re.ldrd=(x.ldrd&&rd[x.r]&&y.ldrd)||(x.ldru&&ru[x.r]&&y.lurd);
re.luru=(x.luru&&ru[x.r]&&y.luru)||(x.lurd&&rd[x.r]&&y.ldru);
re.luld=x.luld||(x.luru&&ru[x.r]&&y.luld&&rd[x.r]&&x.ldrd);
re.rurd=y.rurd||(y.luru&&ru[x.r]&&x.rurd&&rd[x.r]&&y.ldrd);
re.lurd=(x.luru&&ru[x.r]&&y.lurd)||(x.lurd&&rd[x.r]&&y.ldrd);
re.ldru=(x.ldrd&&rd[x.r]&&y.ldru)||(x.ldru&&ru[x.r]&&y.luru);
}
void build(int p,int ll,int rr)
{
if(ll==rr)
{
l(p)=ll,r(p)=rr;
luru(p)=ldrd(p)=true;
return ;
}
int mid=(ll+rr)>>1;
build(p<<1,ll,mid);
build(p<<1|1,mid+1,rr);
update(p);
}
void change1(int p,int des,bool up,bool val)
{
int mid=(l(p)+r(p))>>1;
if(mid==des)
{
if(up) ru[des]=val;
else rd[des]=val;
update(p);
return ;
}
if(des<=mid) change1(p<<1,des,up,val);
else change1(p<<1|1,des,up,val);
update(p);
}
void change2(int p,int des,bool val)
{
if(l(p)==r(p))
{
luld(p)=rurd(p)=lurd(p)=ldru(p)=val;
return ;
}
int mid=(l(p)+r(p))>>1;
if(des<=mid) change2(p<<1,des,val);
else change2(p<<1|1,des,val);
update(p);
}
SegmentTree ask(int p,int ll,int rr)
{
if(ll<=l(p)&&r(p)<=rr) return tree[p];
int mid=(l(p)+r(p))>>1;
if(rr<=mid) return ask(p<<1,ll,rr);
else if(ll>mid) return ask(p<<1|1,ll,rr);
else
{
SegmentTree re;
update(re,ask(p<<1,ll,rr),ask(p<<1|1,ll,rr));
return re;
}
}
int main()
{
n=read();
build(1,1,n);
while(true)
{
char opt=readc();
if(opt=='E') break;
int x=read(),y=read(),xx=read(),yy=read();
if(y>yy) swap(x,xx),swap(y,yy);
if(opt=='C')
{
if(y==yy) change2(1,y,false);
else change1(1,y,x==1,false);
}
else if(opt=='O')
{
if(y==yy) change2(1,y,true);
else change1(1,y,x==1,true);
}
else if(opt=='A')
{
SegmentTree ll=ask(1,1,y),mid=ask(1,y,yy),rr=ask(1,yy,n);
if(x==1&&xx==1)
{
if(mid.luru||(ll.rurd&&mid.ldru)||(mid.lurd&&rr.luld)||(ll.rurd&&mid.ldrd&&rr.luld)) puts("Y");
else puts("N");
}
else if(x==2&&xx==2)
{
if(mid.ldrd||(ll.rurd&&mid.lurd)||(mid.ldru&&rr.luld)||(ll.rurd&&mid.luru&&rr.luld)) puts("Y");
else puts("N");
}
else if(x==1&&xx==2)
{
if(mid.lurd||(ll.rurd&&mid.ldrd)||(mid.luru&&rr.luld)||(ll.rurd&&mid.ldru&&rr.luld)) puts("Y");
else puts("N");
}
else if(x==2&&xx==1)
{
if(mid.ldru||(ll.rurd&&mid.luru)||(mid.ldrd&&rr.luld)||(ll.rurd&&mid.lurd&&rr.luld)) puts("Y");
else puts("N");
}
}
}
return 0;
}

Luogu P4246 [SHOI2008]堵塞的交通(线段树+模拟)的更多相关文章

  1. BZOJ1018[SHOI2008]堵塞的交通——线段树

    题目描述 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总 ...

  2. BZOJ.1018.[SHOI2008]堵塞的交通(线段树维护连通性)

    题目链接 只有两行,可能的路径数不多,考虑用线段树维护各种路径的连通性. 每个节点记录luru(left_up->right_up),lurd,ldru,ldrd,luld,rurd,表示这个区 ...

  3. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)

    题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...

  4. bzoj1018/luogu4246 堵塞的交通 (线段树)

    对于一个区间四个角的点,可以用线段树记下来它们两两的联通情况 区间[l,r]通过两个子区间[l,m],[m+1,r]来更新,相当于合并[l,m],[m+1,r],用(m,m+1)这条边来合并 查询a, ...

  5. P4246 [SHOI2008]堵塞的交通

    思路 同LOJ121 动态图连通性的板子 好像有很神的线段树做法,不会,先码住 代码 #include <cstdio> #include <algorithm> #inclu ...

  6. BZOJ1018 堵塞的交通(线段树)

    题目很好明白,然后实现很神奇.首先如果考虑并查集的话,对于删边和加边操作我们无法同时进行.然后暴力分块的话,复杂度是O(n sqrt n) ,不是很优.于是看了题解,发现了线段树的神奇用途. 我们维护 ...

  7. BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3064  Solved: 1027[Submi ...

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

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

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

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

随机推荐

  1. IOS自动化打包介绍

    IOS自动化打包介绍  标签: app打包 , Ios打包 , iphone打包 , iphone自动化打渠道包    分类:无线客户端技术, 贴吧技术 摘要 随着苹果手持设备用户的不断增加,ios应 ...

  2. hdu多校第九场 1006 (hdu6685) Rikka with Coin 暴力

    题意: 有一些1毛,2毛,5毛,1块的钢镚,还有一些价格不同的商品,现在要求你带一些钢镚,以保证这些商品中任选一件都能正好用这些钢镚付账,问最少带多少钢镚. 题解: 对于最优解,1毛的钢镚最多带1个, ...

  3. LeetCode 1037. Valid Boomerang (有效的回旋镖)

    题目标签:Math 题目给了我们三个点,让我们判断这三个点是否在一条直线上. 利用斜率 k = (y1 - y0) / (x1 - x0) 来判断,如果 三个点 abc, ab 的斜率 = bc 的斜 ...

  4. (转)linux下装tomcat

    转载于:http://www.linuxidc.com/Linux/2016-11/136959.htm (linux社区) 1 tomcat介绍 Tomcat 是由 Apache Foundatio ...

  5. 使用neo4j图数据库的import工具导入数据 -方法和注意事项

    背景 最近我在尝试存储知识图谱的过程中,接触到了Neo4j图数据库,这里我摘取了一段Neo4j的简介: Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌 ...

  6. vue echarts 给饼图中间添加文字 ,并且添加多个样式

    最近根据设计要求写了一个统计图,以下是设计要求,要求中间文字分别是总数和汉字,样式分别不同 好吧具体的解决方案如下 方案一 series: [ { type:'pie', radius: ['50%' ...

  7. Cats Transport

    Cats Transport 现在有n座山,第i座山的坐标为\(d_i\),初始p个饲养员在山1,有m只猫,每只猫有一个属性\(h_i,t_i\)表示猫i 在\(h_i\)以及它在\(t_i\)时间后 ...

  8. Python自学:第五章 使用range( )创建数字列表

    # -*- coding: GBK -*- number = list(range(1,6)) print(number) 输出为: [1, 2, 3, 4, 5] 2. # -*- coding: ...

  9. redis笔记_源码_简单动态字符串SDS

    参照:https://zcheng.ren/sourcecodeanalysis/theannotatedredissourcesds/#sds%E5%B0%8F%E7%BB%93 这里用char b ...

  10. JS函数进阶

    函数的定义方式 函数声明 函数表达式 new Function 函数声明  function foo () { } 函数表达式  var foo = function () { ​ } 函数声明与函数 ...