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 ...
随机推荐
- linux配置网路 设定主机名 ssh bash命令 通配符
临时配置网络(ip,网关,dns) #ifconfig ens33 192.168.185/24 #ens33网卡名称.192.168.185/24是要配置的ip地址/子网掩码 #vim /etc/r ...
- Pythagorean Triples(Codeforces Round #368 (Div. 2) + 构建直角三角形)
题目链接: https://codeforces.com/contest/707/problem/C 题目: 题意: 告诉你直角三角形的一条边,要你输出另外两条边. 思路: 我们容易发现除2外的所有素 ...
- classList属性
1.传统方法: 在操作类名的时候,需要通过className属性添加.删除和替换类名.如下面例子: ? 1 <div class="bd user disabled"> ...
- react 带参数事件方法不立即执行
handleClick:()=>{this.to_step('to_step3_2')}}
- Hibernate5笔记5--关联关系映射
关联关系映射: 关联关系,是使用最多的一种关系,非常重要.在内存中反映为实体关系,映射到DB中为主外键关系.实体间的关联,即对外键的维护.关联关系的发生,即对外键数据的改变. 外键:外面的主键,即,使 ...
- 我应该记录一下我不太了解的一些c语言函数
当然,现在还不分类 fmemopen getpagesize()
- 【codeforces】【比赛题解】#851 CF Round #432 (Div.2)
cf真的难…… 点我浏览丧题. [A]Arpa和她对墨西哥人浪的研究 Arpa正在对墨西哥人浪进行研究. 有n个人站成一排,从1到n编号,他们从时刻0开始墨西哥人浪. 在时刻1,第一个人站起来.在时刻 ...
- 转载-SVN常用命令
SVN(Subversion)是一个自由.开源的项目源代码版本控制工具.目前,绝大多数开源软件和企业代码管理,都使用SVN作为代码版本管理软件. Subversion将文件存放在中心版本库里,这个版本 ...
- Python爬虫之三种网页抓取方法性能比较
下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块. 1. 正则表达式 如果你对正则表达式还不熟悉,或是需要一些提 ...
- 【前端开发】前端引入公共部分footer header的几种方法,及iframe自适应高度js
一.引入页面几种方法 1.IFrame引入,看看下面的代码 <iframe frameborder=0 border=0 width=300 height=300 ...