题目链接


题目大意


解题思路:

我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是O(n2)O(n^2)O(n2)

  1. 首先我们考虑这种动态加边删边的问题,如果是离线的话,那就是线段树分治+可撤销的并查集的模板题
  2. 但是这是强制在线,但是这是虚伪的强制在线就是,每次个操作最多有两种的结果。
    lst={0,1}lst=\{0,1\}lst={0,1}, 最多也就2×m2\times m2×m个操作
  3. 就是我们有条有若干段存在的时间,我们插进线段树里面,用线段树去维护撤销顺序
  4. 首先我们先把两种结果都插进线段树里面,注意线段树分治本质是一个半在线算法
  5. 严格来说我们一开始只是把操作给划分成logloglog块,但是没有调用并查集
  6. 最后一次对整个线段树来个整题的遍历,实际上线段树上面的遍历其实也和你在线处理没什么去区别,你用map去维护选择的边,因为你每次都是递归到叶子节点里面那么本质上也就是再在线处理,然后在加边的时候没有被选择过的边就不要加
    写了个假板子调了半天

AC code

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 500010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}
int n, m, k;
struct Edge {int op, x, y;
}e[maxn];
unordered_map<int,int> mp[maxn];
struct dsu {int fa[maxn], siz[maxn];struct inf {int fx, fy;};vector<inf> stk;void init(int n) {stk.clear();for(int i = 0; i <= n; ++ i) fa[i] = i, siz[i] = 1;}int find(int x) {return fa[x] == x ? x : find(fa[x]);}void merge(int x, int y) {int fx = find(x);int fy = find(y);if(fx == fy) return;if(siz[fx] > siz[fy]) swap(fx,fy);fa[fx] = fy;siz[fy] += siz[fx];stk.push_back({fx,fy});}
}dsu;int las=0;struct Segtree {vector<PII> q[maxn<<2];void update(int rt, int l, int r, int L, int R, PII idx) {if(L <= l && R >= r) {q[rt].push_back(idx);return;}if(L <= mid) update(Lson,L,R,idx);if(R > mid) update(Rson,L,R,idx);}void dfs(int rt, int l, int r) {int lasttop = dsu.stk.size();for(auto it : q[rt]) {if(!mp[it.first][it.second]) continue;dsu.merge(it.first,it.second);}        if(l == r) { // 叶子节点跟新答案int x = (e[l].x + las - 1) % n + 1;int y = (e[l].y + las - 1) % n + 1;if(x > y) swap(x,y);if(e[l].op == 2) {las = (dsu.find(x) == dsu.find(y));cout << las;} else mp[x][y] ^= 1;} else {dfs(Lson);dfs(Rson);}while((int)dsu.stk.size() > lasttop) { // 插销dsuauto it = dsu.stk.back();dsu.stk.pop_back();dsu.fa[it.fx] = it.fx;dsu.siz[it.fy] -= dsu.siz[it.fx];}}
} sgt;int main() {read(n,m);dsu.init(n);for(int i = 1; i <= m; ++ i) {int op, x, y;read(op, x, y);e[i] = {op,x,y};if(op == 1) {for(int j = 0; j <= 1; ++ j) {int l = (x + j - 1) % n + 1;int r = (y + j - 1) % n + 1;if(l > r) swap(l,r);if(mp[l].count(r) && mp[l][r] <= i) sgt.update(1,1,m+1,mp[l][r],i,{l,r});mp[l][r] = i + 1;}} }for(int i = 1; i <= n; ++ i) {for(auto it : mp[i]) if(it.second != m+1)sgt.update(1,1,m+1,it.second,m+1,{i,it.first});mp[i].clear();}sgt.dfs(1,1,m+1);return 0;
}

线段树分治 ---- CF1217F - Forced Online Queries Problem(假离线 可撤销并查集 + 线段树分治)详解相关推荐

  1. 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)

    题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...

  2. 【BZOJ4025】二分图(可撤销并查集+线段树分治)

    题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...

  3. 线段树分治 ---- F. Extending Set of Points(线段树分治 + 可撤销并查集)

    题目链接 题目大意: 你有个点集合SSS,每次往集合里面加点或者删点(如果要加的点出现过),如果(x1,y1),(x2,y1),(x1,y2),(x2,y2)(x1,y1),(x2,y1),(x1,y ...

  4. 暑期集训5:并查集 线段树 练习题B: HDU - 1213 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题B  --   HDU - 1213 How Many Tables Today is Ignatius' birthday. He invites ...

  5. 暑期集训5:并查集 线段树 练习题G: HDU - 1754

    2018学校暑期集训第五天--并查集 线段树 练习题G  --   HDU - 1754 I Hate It 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.  这让 ...

  6. 暑期集训5:并查集 线段树 练习题F:  HDU - 1166 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题F  --   HDU - 1166 敌兵布阵 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A ...

  7. 暑期集训5:并查集 线段树 练习题A:  HDU - 1232 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题A  --   HDU - 1232 畅通工程 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅 ...

  8. UVA1455 - Kingdom(并查集 + 线段树)

    UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...

  9. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

最新文章

  1. Oracle定时执行存储过程
  2. Ubuntu“无法获得锁\加锁”解决方案
  3. expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.spring
  4. 高可用集群技术之RHCS应用详解(一)
  5. 10 过滤器和监听器
  6. oracle:实现滑动平均效果
  7. 加密芯片在游戏行业内的应用
  8. 官方文档---ubuntu 安装OpenStack
  9. springbootredis连接池配置优化_spring boot rest 接口集成 spring security(2) – JWT配置
  10. VS 2012 No exports were found that match the constraint 解决办法
  11. 十个JDBC的最佳实践
  12. 隐马尔科夫模型(HMM)
  13. python | 中国地形图背景画站点数量空间分布图(更新)
  14. 阿里巴巴Java开发规范手册(详尽版)——免费下载
  15. electron tray click right click
  16. 理论结合实际:如何调试神经网络并检查梯度
  17. vue跳转新页面链接以及url 转码
  18. IPv6-GRE 隧道技术
  19. 猎头职场:领导给的任务如何让自己被器重
  20. python+django网吧会员管理系统

热门文章

  1. 线性回归的改进-岭回归
  2. 从零开始一起学习SLAM | 三维空间刚体的旋转
  3. 快速指南:使用OpenCV预处理神经网络中的面部图像
  4. 极限编程 (Extreme Programming) 和用户故事 (User Stories) 的关系
  5. Faiss教程:索引(2)
  6. Blockchain实现详细手册
  7. API和schema开发过程问题汇总
  8. 使用nodejs安装Vue-cli
  9. Android RecyclerView添加Header头部
  10. eclipse安装Spket插件