题目链接

题解

早就想写线段树分治的题了。

对于每条边,它存在于一段时间

我们按时间来搞

我们可把一条边看做一条线段

我们可以模拟线段树操作,不断分治下去

把覆盖\(l-r\)这段时间的线段筛选出来,用并查集维护联通性,回溯时撤销操作

注意不能使用路径压缩(不能破坏树的结构,方便撤销操作)

Code

#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std; inline int gi() {
int f = 1, s = 0;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -1, c = getchar();
while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
return f == 1 ? s : -s;
} const int N = 10010, M = 200010; struct question {
int time, u, v;
}q[M];
int ql, w; struct bian {
int u, v, s, e;
};
vector<bian> g;
map<pair<int, int>, int> Mp;
int siz[N], fa[N];
inline int find(int x) {
return x == fa[x] ? x : find(fa[x]);
}
pair<int, int> stk[M];
int top; void link(int x, int y) {//按秩合并
x = find(x); y = find(y);
if (x == y) {
stk[++top] = make_pair(0, 0);
return ;
}
if (siz[x] < siz[y]) swap(x, y);
stk[++top] = make_pair(x, y);//y接在x上
fa[y] = x;
siz[x] += siz[y];
return ;
} void clear() {//撤销操作
int x = stk[top].first, y = stk[top--].second;
if (!x && !y) return ;
fa[y] = y;
siz[x] -= siz[y];
return ;
} void divide(int l, int r, vector<bian> E) {
vector<bian> L, R;
int tmp = top, mid = (l + r) >> 1;
for (int i = 0; i < (int)E.size(); i++) {
if (E[i].s <= l && E[i].e >= r) link(E[i].u, E[i].v);
else {
if (E[i].s <= mid) L.push_back(E[i]);
if (E[i].e > mid) R.push_back(E[i]);
}
}
if (l == r) {
while (q[w].time == l && w <= ql) {
if (find(q[w].u) == find(q[w].v)) printf("Yes\n");
else printf("No\n");
w++;
}
if (w > ql) exit(0);
return ;
}
else divide(l, mid, L), divide(mid+1, r, R);
while (top > tmp) clear();
return ;
} int main() {
int n = gi(), m = gi(), x, y;
char s[10];
for (int i = 1; i <= m; i++) {
cin >> s >> x >> y;
if (x > y) swap(x, y);
if (s[0] == 'C') {
if (Mp.find(make_pair(x, y)) == Mp.end())
g.push_back((bian){x, y, i, m}), Mp[make_pair(x, y)] = g.size()-1;
}
else if (s[0] == 'D') {
g[Mp[make_pair(x, y)]].e = i-1;
Mp.erase(Mp.find(make_pair(x, y)));
}
else q[++ql] = (question) {i, x, y};
}
/*for (int i = 0; i < g.size(); i++)
printf("%d %d %d %d\n", g[i].u, g[i].v, g[i].s, g[i].e);*/
w = 1;
for (int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1;
divide(1, m, g);
return 0;
}

最新文章

  1. Xamarin中使用DatePickerDialog的相关问题
  2. C# 顺序高斯(Gauss)消去法计算一元多次方程组
  3. mysql 主从 重新同步
  4. adb permission denied
  5. hihoCoder 1160 攻城略地
  6. Python中的日志管理Logging模块
  7. 46.谈谈SDRAM的作用
  8. 【BZOJ】【1067】 【SCOI2007】降雨量
  9. SuperSocket与Netty之实现protobuf协议,包括服务端和客户端
  10. UML--核心元素之分析类
  11. knockout简单实用教程3
  12. Yii 2.0 ActiveForm生成表单 ,控制表单label和filed样式,filed一旦报错,前面lable颜色跟着变,看图,帮你解决
  13. Jquery blokckUI 快速入门
  14. JavaScript设计模式之一封装
  15. Java并发编程面试题 Top 50 整理版
  16. WordCount结对项目
  17. python3 “POST data should be bytes or an iterable of bytes...”的解决方法
  18. source insight常用设置问题
  19. Jenkins之常用变量
  20. IntelliJ IDEA 版本控制器 - Git

热门文章

  1. SpringBoot25 gradle安装、利用gradle创建SrpingBoot项目
  2. iBase4j前端01_bootstrap-suggest json-server模拟后台数据、bootstrap-suggest环境搭建、开启bootstrap-suggest的post和put请求
  3. 599. Minimum Index Sum of Two Lists两个餐厅列表的索引和最小
  4. opennebula kvm日志
  5. Django框架 之 modelform组件
  6. jqgrid扩展 获取表单数据
  7. zigbee--绑定
  8. Visual Studio OpenCV 开发环境配置
  9. Ubuntu普通用户使用串口设备
  10. DataType--类型基础