线段树分治+并查集

线段树本身就是分治结构,碰见这种带删除修改的题目是再合适不过的,我们对于每段修改区间在线段树上打标记,每次路过就进行修改,叶子结点表及答案,先把所有修改在线段树上标记,然后dfs就行了

但是并查集怎么恢复呢?我们只要维护一个栈,保存某次操作之前这两个点的信息,dfs本身就是利用栈来操作,那么每次回溯就用栈的信息恢复之前的样子就行了

#include<bits/stdc++.h>
using namespace std;
const int N = ;
int c, tot, cnt, top, ask;
int fa[N], l[N], r[N], d[N], mark[N];
bool ans[N];
struct dsu {
int u, v, fa, du, dv;
dsu(int u = , int v = , int fa = , int du = , int dv = ) : u(u), v(v), fa(fa), du(du), dv(dv) {}
} st[N];
pair<int, int> operation[N];
map<pair<int, int>, int> mp;
vector<pair<int, int> > tree[N << ], q[N << ];
char opt[];
inline int read()
{
int x = , f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = x * + c - ''; c = getchar(); }
return x * f;
}
int find(int x)
{
return x == fa[x] ? x : find(fa[x]);
}
int id(int x, int y)
{
return (x - ) * c + y;
}
void unite(pair<int, int> o)
{
int x = find(o.first), y = find(o.second);
if(d[x] > d[y]) swap(x, y);
st[++top] = dsu(x, y, fa[x], d[x], d[y]);
if(x != y)
{
d[y] += d[x];
fa[x] = y;
}
}
void del(int now)
{
while(top != now)
{
dsu x = st[top];
fa[x.u] = x.fa;
d[x.u] = x.du;
d[x.v] = x.dv;
--top;
}
}
void update(int l, int r, int x, int a, int b, pair<int, int> o)
{
if(l > b || r < a) return;
if(l >= a && r <= b)
{
tree[x].push_back(o);
return;
}
int mid = (l + r) >> ;
update(l, mid, x << , a, b, o);
update(mid + , r, x << | , a, b, o);
}
void dfs(int l, int r, int x)
{
int now = top;
for(int i = ; i < tree[x].size(); ++i) unite(tree[x][i]);
if(l == r)
{
for(int i = ; i < q[l].size(); ++i)
{
pair<int, int> o = q[l][i];
if(find(o.first) == find(o.second)) puts("Y");
else puts("N");
}
del(now);
return;
}
int mid = (l + r) >> ;
dfs(l, mid, x << );
dfs(mid + , r, x << | );
del(now);
}
int main()
{
// freopen("bzoj_1018.in", "r", stdin);
// freopen("bzoj_1018.out", "w", stdout);
memset(l, 0x3f3f, sizeof(l));
c = read();
for(int i = ; i <= * c; ++i)
{
fa[i] = i;
d[i] = ;
}
while(scanf("%s", opt))
{
if(opt[] == 'E') break;
++tot;
int r1 = read(), c1 = read(), r2 = read(), c2 = read(), u = id(r1, c1), v = id(r2, c2);
if(u > v) swap(u, v);
if(opt[] == 'O')
{
if(mp.find(make_pair(u, v)) != mp.end()) continue;
l[++cnt] = tot;
operation[cnt] = make_pair(u, v);
mp[make_pair(u, v)] = cnt;
}
if(opt[] == 'C')
{
if(mp.find(make_pair(u, v)) == mp.end()) continue;
r[mp[make_pair(u, v)]] = tot - ;
mp.erase(make_pair(u, v));
}
if(opt[] == 'A') q[tot].push_back(make_pair(u, v));
}
for(int i = ; i <= cnt; ++i)
{
if(!r[i]) r[i] = tot;
update(, tot, , l[i], r[i], operation[i]);
}
dfs(, tot, );
for(int i = ; i <= ask; ++i) if(ans[i]) puts("Y");
else puts("N");
// fclose(stdin);
// fclose(stdout);
return ;
}

bzoj1018的更多相关文章

  1. 【线段树】bzoj1018 [SHOI2008]堵塞的交通traffic

    线段树的每个叶子节点存一列. 每个节点维护六个域,分别是左上左下.左上右上.左上右下.左下右上.左下右下.右上右下在区间内部的连通性,不考虑绕出去的情况. 初始每个叶子的左上左下.右上右下是连通的. ...

  2. 【bzoj1018】 SHOI2008—堵塞的交通traffic

    http://www.lydsy.com/JudgeOnline/problem.php?id=1018 (题目链接) 题意 一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道 ...

  3. 【bzoj1018】堵塞的交通

    [bzoj1018]堵塞的交通 题意 一个\(2*n\)的格子,相邻格子之间有一条道路.初始时道路是不通的. \(C\)个操作,每个操作为三种中的一种:(1)某条道路连起来:(2)某条道路断开:(3) ...

  4. 【BZOJ1018】堵塞的交通(线段树)

    [BZOJ1018]堵塞的交通(线段树) 题面 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可 以被看成是一个2行C列的矩形网 ...

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

    动态图的连通性当然是可以用LCT维护的.但这相当的不优美,毕竟这样做没有用到任何该图的性质,LCT自带的大常数也会使其跑得非常慢. 考虑用线段树维护区间左右端四个点之间各自的连通性(仅经过该区间内路径 ...

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

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

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

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

  8. 【BZOJ1018】堵塞的交通traffic(线段树,网格图,连通性)

    题意:一个2行C列的矩形网格图,网格上的每个点代表一个城市,相邻的城市之间有一条道路 一开始每条道路都是堵塞的,堵塞即为不可经过.经过一些操作后,可能某些道路通畅了,也可能某些道路堵塞了 多次询问,询 ...

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

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

  10. BZOJ1018 [SHOI2008]堵塞的交通traffic

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

随机推荐

  1. break和continue在多重循环中使用

    break和continue在多重循环中使用 关于break和continue在java中,break的作用是跳出循环,continue的作用是跳出本次循环. 我们一般情况下,这样使用: public ...

  2. day02 Python完结

    一. 常用数据类型及内置法 1 列表 定义: 列表是Python中内置有序.可变序列,列表的所有元素放在一对中括号“[]”中,并使用逗号分隔开: 当列表元素增加或删除时,列表对象自动进行扩展或收缩内存 ...

  3. css 实现鼠标滑过流光效果

    来划我啊 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...

  4. Java 数组中寻找最大子数组

    程序设计思想: 依次将数组划分开,先判断一个元素的单个数组大小,接下来两个,依次上升,最后将所得结果进行比较赋值,输出最大结果. 1 package ketangTest; //张生辉,康治家 201 ...

  5. python之cookbook-day02

    第一章:数据结构和算法 1.2 解压可迭代对象赋值给多个变量 问题: 如果一个可迭代对象的元素个数超过变量个数时,会抛出一个 ValueError .那么 怎样才能从这个可迭代对象中解压出 N 个元素 ...

  6. ios 7以后 隐藏顶部状态栏

    iOS 7 以后,之前隐藏顶部状态栏的方法都已经失效.以下介绍的方法是全部兼容的. 修改xode工程里的 Info.plist 增加 Status bar is initially hidden一行, ...

  7. git删除远程remote分支

    git 命令如下: git push origin --delete <远程分支名字>

  8. HDU 4902 (牛叉的线段树)

    Nice boat Problem Description There is an old country and the king fell in love with a devil. The de ...

  9. TCP/IP协议1

    1.分层 应用层 telent 远程登录,ftp 文件传输协议,smtp 简单邮件传送协议 snmp 简单网络管理协议 email 运输层  tcp(提供可靠的数据通信)和udp(数据报的分组从一台主 ...

  10. 20181010关于pt-kill自动杀死运行超长的进程

    转自: http://blog.chinaunix.net/uid-16844903-id-4442030.htmlhttp://blog.chinaunix.net/uid-31396856-id- ...