博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj1018
阅读量:4356 次
发布时间:2019-06-07

本文共 2811 字,大约阅读时间需要 9 分钟。

线段树分治+并查集

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

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

#include
using namespace std;const int N = 100010;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 = 0, int v = 0, int fa = 0, int du = 0, int dv = 0) : u(u), v(v), fa(fa), du(du), dv(dv) {}} st[N];pair
operation[N];map
, int> mp;vector
> tree[N << 2], q[N << 2];char opt[10];inline int read(){ int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; 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 - 1) * c + y;}void unite(pair
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
o){ if(l > b || r < a) return; if(l >= a && r <= b) { tree[x].push_back(o); return; } int mid = (l + r) >> 1; update(l, mid, x << 1, a, b, o); update(mid + 1, r, x << 1 | 1, a, b, o);}void dfs(int l, int r, int x){ int now = top; for(int i = 0; i < tree[x].size(); ++i) unite(tree[x][i]); if(l == r) { for(int i = 0; i < q[l].size(); ++i) { pair
o = q[l][i]; if(find(o.first) == find(o.second)) puts("Y"); else puts("N"); } del(now); return; } int mid = (l + r) >> 1; dfs(l, mid, x << 1); dfs(mid + 1, r, x << 1 | 1); 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 = 1; i <= 2 * c; ++i) { fa[i] = i; d[i] = 1; } while(scanf("%s", opt)) { if(opt[0] == '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[0] == '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[0] == 'C') { if(mp.find(make_pair(u, v)) == mp.end()) continue; r[mp[make_pair(u, v)]] = tot - 1; mp.erase(make_pair(u, v)); } if(opt[0] == 'A') q[tot].push_back(make_pair(u, v)); } for(int i = 1; i <= cnt; ++i) { if(!r[i]) r[i] = tot; update(1, tot, 1, l[i], r[i], operation[i]); } dfs(1, tot, 1); for(int i = 1; i <= ask; ++i) if(ans[i]) puts("Y"); else puts("N");// fclose(stdin);// fclose(stdout); return 0;}
View Code

 

转载于:https://www.cnblogs.com/19992147orz/p/7281414.html

你可能感兴趣的文章
关于jQuery表单校验的应用
查看>>
matplotlib----初探------5直方图
查看>>
jquery之ajax
查看>>
Pro Git(中文版)
查看>>
解决phpmyadmin-1800秒超时链接失效问题
查看>>
OpenGL第十一节:拉伸和过滤
查看>>
AlertDialog的onCreateDialog与onPrepareDialog用法
查看>>
swift菜鸟入门视频教程-12-21讲
查看>>
PL/SQL 异常处理程序
查看>>
javascript小白学习指南1---0
查看>>
div:给div加滚动栏 div的滚动栏设置
查看>>
java随机函数使用方法Random
查看>>
链表中环的入口结点
查看>>
凤姐讲学英语
查看>>
ActionBar
查看>>
5种方法实现数组去重
查看>>
2~15重点语法
查看>>
flask中的CBV,flash,Flask-Session,WTForms - MoudelForm,DBUtils 数据库连接池
查看>>
最近整理的提供免费代理列表的几个网站
查看>>
探偵ガリレオー転写る2
查看>>