Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)
题面
题解
考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治。
具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内,那就把它用并查集并起来。最后对于一个询问,直接用并查集找就好了。
但是因为有撤销操作,所以在并查集合并的时候,我们将需要合并的两个点放进栈中,最后栈序撤销,所以只能考虑按秩合并而不能路径压缩。
#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using std::min; using std::max;
using std::sort; using std::swap;
using std::unique; using std::lower_bound;
using std::map; using std::vector;
typedef long long ll;
template<typename T>
void read(T &x) {
int flag = 1; x = 0; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}
const int N = 2e5 + 10;
int n, id[3][N], q_num, top, fa[N], siz[N], cnt;
map<int, int> G[N];
struct Edge { int u, v, beg, end; };
struct Node { int x, y; } q[N], stk[N << 2];
vector<Edge> e;
int find(int x) { while(fa[x] != x) x = fa[x]; return x; }
inline void merge(int x, int y) {
int fx = find(x), fy = find(y);
if(siz[fx] > siz[fy]) swap(fx, fy);
fa[fx] = fy, siz[fy] += siz[fx], stk[++top] = (Node){fx, fy};
}
void doit (int l, int r, vector<Edge> E) {
vector<Edge> L, R;
int mid = (l + r) >> 1, tmp = top;
for(vector<Edge>::iterator it = E.begin(); it != E.end(); ++it)
if(it->beg <= l && it->end >= r) merge(it->u, it->v);
else {
if(it->beg <= mid) L.push_back(*it);
if(it->end > mid) R.push_back(*it);
}
if(l == r) puts(find(q[l].x) == find(q[l].y) ? "Y" : "N");
else doit(l, mid, L), doit(mid + 1, r, R);
while(top > tmp) {
int x = stk[top].x, y = stk[top--].y;
fa[x] = x, siz[y] -= siz[x];
}
}
int main () {
read(n);
for(int i = 1; i <= n; ++i)
id[1][i] = ++cnt, id[2][i] = ++cnt;
while(true) {
char s[10]; int r1, c1, r2, c2;
scanf("%s", s); if(s[0] == 'E') break;
read(r1), read(c1), read(r2), read(c2);
if(s[0] == 'O') {
G[id[r1][c1]][id[r2][c2]] = G[id[r2][c2]][id[r1][c1]] = e.size();
e.push_back((Edge){id[r1][c1], id[r2][c2], q_num + 1, -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] = (Node){id[r1][c1], id[r2][c2]};
}
for(vector<Edge>::iterator it = e.begin(); it != e.end(); ++it)
if(it->end == -1) it->end = q_num;
for(int i = 1; i <= n + n; ++i) fa[i] = i, siz[i] = 1;
doit(1, q_num, e);
return 0;
}
Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)的更多相关文章
- Luogu P4246 [SHOI2008]堵塞的交通(线段树+模拟)
P4246 [SHOI2008]堵塞的交通 题意 题目描述 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个\(2\)行\(C\)列的矩形 ...
- 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)
题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ...
- 洛谷P4121 [WC2005]双面棋盘(线段树套并查集)
传送门 先膜一下大佬->这里 据说这题正解是LCT,然而感觉还是线段树套并查集的更容易理解 我们对于行与行之间用线段树维护,每一行内用并查集暴力枚举 每一行内用并查集暴力枚举连通块这个应该容易理 ...
- 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)
LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...
- BZOJ1018[SHOI2008]堵塞的交通——线段树
题目描述 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总 ...
- BZOJ.1018.[SHOI2008]堵塞的交通(线段树维护连通性)
题目链接 只有两行,可能的路径数不多,考虑用线段树维护各种路径的连通性. 每个节点记录luru(left_up->right_up),lurd,ldru,ldrd,luld,rurd,表示这个区 ...
- BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)
传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...
- LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset
题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...
- 【洛谷P4319】 变化的道路 线段树分治+LCT
最近学了一下线段树分治,感觉还蛮好用... 如果正常动态维护最大生成树的话用 LCT 就行,但是这里还有时间这一维的限制. 所以,我们就把每条边放到以时间为轴的线段树的节点上,然后写一个可撤销 LCT ...
随机推荐
- JS对象中的原型
对象的原型:每个对象都连接一个原型对象,并且它可以从中继承属性.所有通过对象字面量创建的对象都连接到object.prototype.当你创建一个新对象时,你可以选择某个对象作为它的原型.原型连接在更 ...
- ArchLinux升级后deadbeef无法正常启动的解决办法
deadbeef是一款简约而不简单的音乐播放器, 占资源少, 支持的格式却不少. 昨天对ArchLinux进行了一次全面升级, 经历种种惊险, 终于跨越了从 glibc-2.16 到 glibc-2. ...
- Is It A Tree? 挂着并查集的帽子招摇撞骗
Description A tree is a well-known data structure that is either empty (null, void, nothing) or is a ...
- tensorflow环境安装
tensorflow环境安装1.安装虚拟机Virtrualbox下载地址:https://www.virtualbox.org/wiki/Downloads 2.下载安装Ubuntu镜像下载地址:ht ...
- ES6简单总结
1.变量声明let和const 我们都是知道在ES6以前,var关键字声明变量.无论声明在何处,都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部).这就是函数变量提升例如: functi ...
- 【多视图几何】TUM 课程 第2章 刚体运动
课程的 YouTube 地址为:https://www.youtube.com/playlist?list=PLTBdjV_4f-EJn6udZ34tht9EVIW7lbeo4 .视频评论区可以找到课 ...
- 利用SSLStrip截获https协议--抓取邮箱等密码
1.SSL解析 SSL 是 Secure Socket Layer 的简称, 中文意思是安全套接字层,由 NetScape公司所开发,用以保障在 Internet 上数据传输的安全,确保数据在网络的传 ...
- Linux查看用户密码修改时间
在/etc/shadow文件里面,第三个字段标识表示密码修改日期:这个是表明上一次修改密码的日期与1970-1-1相距的天数.如果账户自创建后,没有修改过密码,就可以使用这个字段来查找账号创建日期. ...
- Tslib步骤以及出现问题的解决方案【转】
转自:http://forum.eepw.com.cn/thread/267828/1 嵌入式设备中触摸屏使用非常广泛,但触摸屏的坐标和屏的坐标是不对称的,需要校准.校准广泛使用的是开源的tslib. ...
- Linux内核跟踪之syscall tracer 【转】
转自:http://blog.chinaunix.net/uid-20543183-id-1930847.html ------------------------------------------ ...