bzoj1018
线段树分治+并查集
线段树本身就是分治结构,碰见这种带删除修改的题目是再合适不过的,我们对于每段修改区间在线段树上打标记,每次路过就进行修改,叶子结点表及答案,先把所有修改在线段树上标记,然后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的更多相关文章
- 【线段树】bzoj1018 [SHOI2008]堵塞的交通traffic
线段树的每个叶子节点存一列. 每个节点维护六个域,分别是左上左下.左上右上.左上右下.左下右上.左下右下.右上右下在区间内部的连通性,不考虑绕出去的情况. 初始每个叶子的左上左下.右上右下是连通的. ...
- 【bzoj1018】 SHOI2008—堵塞的交通traffic
http://www.lydsy.com/JudgeOnline/problem.php?id=1018 (题目链接) 题意 一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道 ...
- 【bzoj1018】堵塞的交通
[bzoj1018]堵塞的交通 题意 一个\(2*n\)的格子,相邻格子之间有一条道路.初始时道路是不通的. \(C\)个操作,每个操作为三种中的一种:(1)某条道路连起来:(2)某条道路断开:(3) ...
- 【BZOJ1018】堵塞的交通(线段树)
[BZOJ1018]堵塞的交通(线段树) 题面 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可 以被看成是一个2行C列的矩形网 ...
- BZOJ1018 SHOI2008堵塞的交通(线段树)
动态图的连通性当然是可以用LCT维护的.但这相当的不优美,毕竟这样做没有用到任何该图的性质,LCT自带的大常数也会使其跑得非常慢. 考虑用线段树维护区间左右端四个点之间各自的连通性(仅经过该区间内路径 ...
- 【BZOJ1018】[SHOI2008]堵塞的交通
[BZOJ1018][SHOI2008]堵塞的交通 题面 bzoj 洛谷 洛谷 题解 菊队讲要用线段树维护连通性,但是好像没人写 解法一 将所有的加边删边离线,然后以最近删除时间为边权,$LCT$维护 ...
- 【BZOJ1018】[SHOI2008]堵塞的交通traffic 线段树
[BZOJ1018][SHOI2008]堵塞的交通traffic Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个 ...
- 【BZOJ1018】堵塞的交通traffic(线段树,网格图,连通性)
题意:一个2行C列的矩形网格图,网格上的每个点代表一个城市,相邻的城市之间有一条道路 一开始每条道路都是堵塞的,堵塞即为不可经过.经过一些操作后,可能某些道路通畅了,也可能某些道路堵塞了 多次询问,询 ...
- [bzoj1018][SHOI2008]堵塞的交通traffic_线段树
bzoj-1018 SHOI-2008 堵塞的交通traffic 参考博客:https://www.cnblogs.com/MashiroSky/p/5973686.html 题目大意:有一天,由于某 ...
- BZOJ1018 [SHOI2008]堵塞的交通traffic
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
随机推荐
- sql之inner join
这个嘛...经常写sql写的我怀疑自己:算了还是记下来了再强调一遍!再强调一遍!再强调一遍!:虽然很傻逼... inner join(等值连接) 只返回两个表中联结字段相等的行
- cout 按进制数出
头文件: #include<iostream> #include<iomanip> //setbase() #include<bitset> //bitset< ...
- MySQL练习题及答案(复习)
新建一个叫做 review 的数据库,将测试数据脚本导进去.(可以使用Navicat查询功能) /* Navicat MySQL Data Transfer Source Server : DB So ...
- NFS文件服务
安装NFS服务 Yum install nfs-utils –y 2.关闭防火墙 service iptables stop 3./etc/exports NFS服务配置文件 /home/share ...
- __setitem__() __getitem__() __delitem__()
#item系列 和对象使用[]访问值有联系 #obj={'k':'v'} #print(obj) #print(obj['k']) class B: def __getitem__(self, ite ...
- 关于jupyter notebook
直接点击进行跳转阅读:https://zhuanlan.zhihu.com/p/33105153
- 【Codeforces 369C】 Valera and Elections
[链接] 我是链接,点我呀:) [题意] 给你一棵树 让你选择若干个修理点. 这些修理点被选中之后,节点i到1号节点之间的所有"坏路"都会被修好 问最少需要选择多少个点才能将所有的 ...
- 【Codeforces 522B】Photo to Remember
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 模拟题.用set模拟下就好 [代码] import java.io.*; import java.util.*; public class M ...
- Codeforces Round #226 (Div. 2) C题
数论好题 题目要求:求给定序列的素因子如果在给定区间内该数字个数加1; 思路:打表时求出包含给素数因子的数的个数,详见代码 1 #include<cstring> +; scan ...
- hello2 source analisis(notes)
该hello2应用程序是一个Web模块,它使用Java Servlet技术来显示问候语和响应.使用文本编辑器查看应用程序文件,也可以使用NetBeans IDE. 此应用程序的源代码位于 _tut-i ...