题面

题解

这里提供几种不用脑子的算法(当然是离线的)

$\text{LCT}$

记下每条边的删除时间,用$\text{LCT}$维护最大生成树,每次加进一条边时,跟原来那条链上的做比较,删除那条删除时间最短的边即可。

线段树分治

这个算法将每条边的加入和删除时间加入到线段树中,所以在遍历到叶子节点时,那个时刻存在的边都已经在并查集上了,于是直接判断即可。

并查集用按秩合并就可以了,撤销时记得按栈序撤销。

代码

LCT

找$hyj$去

线段树分治

我的写法可能(比较好看)并没有建线段树......

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<vector>
#include<map>
#define RG register
#define clear(x, y) memset(x, y, sizeof(x)) inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
} const int maxn(200010);
struct edge { int from, to, beg, end; };
std::pair<int, int> q[maxn], stk[maxn << 2];
std::vector<edge> e;
std::map<int, int> G[maxn];
int fa[maxn], top, q_num, n, id[2][maxn], cnt, size[maxn];
char s[10]; inline int find(int x) { while(x ^ fa[x]) x = fa[x]; return x; }
inline void merge(int x, int y)
{
int fx = find(x), fy = find(y);
if(fx == fy) return;
if(size[fx] > size[fy]) std::swap(fx, fy);
fa[fx] = fy; size[fy] += size[fx]; stk[++top] = std::make_pair(fx, fy);
} inline void undo()
{
int x = stk[top].first, y = stk[top--].second;
fa[x] = x; size[y] -= size[x];
} inline void Div(int l, int r, std::vector<edge> E)
{
std::vector<edge> L, R;
std::vector<edge>::iterator it;
int mid = (l + r) >> 1, tmp = top;
for(it = E.begin(); it != E.end(); ++it)
if(it -> beg <= l && r <= it -> end) merge(it -> from, it -> to);
else
{
if(it -> beg <= mid) L.push_back(*it);
if(it -> end > mid) R.push_back(*it);
}
if(l == r) printf("%c\n", find(q[l].first) == find(q[l].second) ? 'Y' : 'N');
else Div(l, mid, L), Div(mid + 1, r, R);
while(top > tmp) undo();
} int main()
{
n = read();
for(RG int i = 1; i <= n; i++)
id[0][i] = ++cnt, id[1][i] = ++cnt;
for(RG int r1, c1, r2, c2;;)
{
scanf("%s", s);
if(s[0] == 'E') break;
r1 = read() - 1, c1 = read(), r2 = read() - 1, c2 = read();
if(s[0] == 'O')
{
e.push_back((edge){id[r1][c1], id[r2][c2], q_num + 1, -1});
G[id[r1][c1]][id[r2][c2]] = G[id[r2][c2]][id[r1][c1]] = e.size() - 1;
}
else if(s[0] == 'C') e[G[id[r1][c1]][id[r2][c2]]].end = q_num;
else if(s[0] == 'A') q[++q_num] = std::make_pair(id[r1][c1], id[r2][c2]);
}
for(std::vector<edge>::iterator it = e.begin(); it != e.end(); ++it)
if(it -> end == -1) it -> end = q_num;
for(RG int i = 1; i <= n + n; i++) fa[i] = i, size[i] = 1;
Div(1, q_num, e);
return 0;
}

【SHOI2008】堵塞的交通的更多相关文章

  1. 数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2638  Solved: 864 Descri ...

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

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2247  Solved: 706[Submit ...

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

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

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

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

  5. 【BZOJ1018】[SHOI2008]堵塞的交通

    [BZOJ1018][SHOI2008]堵塞的交通 题面 bzoj 洛谷 洛谷 题解 菊队讲要用线段树维护连通性,但是好像没人写 解法一 将所有的加边删边离线,然后以最近删除时间为边权,$LCT$维护 ...

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

    1018: [SHOI2008]堵塞的交通traffic 链接 分析: 用线段树维护区间的四个端点的联通情况,然后查询的时候,把所有覆盖到的区间合并起来即可. 六种情况左上到右上(左边到右边的情况)… ...

  7. 【bzoj1018】[SHOI2008]堵塞的交通traffic

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2887  Solved: 954[Submit ...

  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 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个 ...

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

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

随机推荐

  1. python process,queue

    #-*- coding:utf-8 -*- from multiprocessing import Process,Queue import os,time,random def write(q): ...

  2. 【[NOI2010]航空管制】

    关于拓扑排序的反建图还是一个非常套路的东西 比如说[HNOI2015]菜肴制作 我们希望使得某一个东西在拓扑序中出现的尽可能早,这个时候就可以建出一张反图来,使得这个东西在反图中的拓扑序尽量靠后,从而 ...

  3. [19/04/25-星期四] GOF23_结构型模式(适配器模式、代理模式)

    一.引言 结构模式:核心作用就是从程序的结构上实现松耦合,从而扩大整体的类结构,用来解决更大的问题. 二.适配器模式(adapter) 生活中假设笔记本是标准的USB接口但是外置键盘是圆形接口,这时候 ...

  4. flutter 配置环境

    1. 下载java SDK https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html c ...

  5. php回调函数数组的排序函数

    array_filter() array_map() sort()升序不保存key resort() asort()升序保存key arsort() ksort()根据key排序 krsort()

  6. js中时间的操作

    var myDate = new Date();myDate.getYear();        //获取当前年份(2位)myDate.getFullYear();    //获取完整的年份(4位,1 ...

  7. No.1 - 制作一个简单的菜单动画效果---百度IFE

    最近比较闲,在家做点训练 http://ife.baidu.com/course/detail/id/18?t=1527144851578#learn CSS3新特性,兼容性,兼容方法总结 https ...

  8. GAutomator,GAutomatorview和Android SDK,Unity配置

    1. 安装和配置JDK 环境配置中: JAVA_HOME:E:\Program Files\java\jdk1.8.0_131 Path:%JAVA_HOME%\bin;%JAVA_HOME%\jre ...

  9. Android性能监控

    Android性能监控 一.搭建Android性能测试环境,参见<Android性能测试之Monkey使用>中内容. 二.启动Android虚拟机,可以通过eclipse启动,也可以通过命 ...

  10. Ubuntu16.04系统中不同版本Python之间的转换

    Ubuntu系统自带的版本是2.7.12 安装好python3.6之后,改变一下Python的优先级(需要root权限). 在使用下面这个命令查看电脑里面有几个Python版本 update-alte ...