线段树分治+并查集

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

最新文章

  1. vim配置及快捷键
  2. c# long转 datetime
  3. C#搭建足球赛事资料库与预测平台(1) 基本介绍
  4. Xlib 窗口属性
  5. 在.NET 应用程序设计中如何选择Class, Abstract Class and Interface
  6. 【转】iOS应用崩溃日志揭秘
  7. HTML与XML总结
  8. php中echo(),print(),print_r()用法
  9. jQuery选择器---基本选择器总结
  10. 实例讲解基于 React+Redux 的前端开发流程
  11. Android进阶(十三)网络爬虫&amp;json应用
  12. mysql导入数据中文乱码_ubuntu
  13. Activiti6-数据库配置-dbconfig(学习笔记)
  14. thinkphp 实现分页
  15. springboot使用jpa+mongodb时,xxxRepository不能Autowired的问题
  16. JEECG第二期深入使用培训(报名截止2014-06-21)
  17. jquery获取点击控件的绝对位置简单实例
  18. Incorrect datetime value
  19. java命令--jmap命令使用(查找内存泄漏对象)
  20. servlet3.0 文件上传功能

热门文章

  1. CentOS下安装微软雅黑字体
  2. vue+webpack+npm搭建的纯前端项目
  3. PHP 结合前端 ajax 爬取网站信息后, 向指定用户发送指定短信;
  4. Q-criterion- definition and post-processing
  5. js中的三种弹框分别是alert(),confirm(),prompt()
  6. vuex----mutation和action的基本使用
  7. opengl 对投影变化函数的理解
  8. kendo中需要kendo.default.min.css
  9. HashMap源码分析2:扩容
  10. HDU 1546 Idiomatic Phrases Game 求助!help!!!