ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-09-29 21:00:02  阅读:219  来源: 互联网

标签:dsu int fy 线段 分治 离线 fx ch


题目链接


题目大意

在这里插入图片描述


解题思路:

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

  1. 首先我们考虑这种动态加边删边的问题,如果是离线的话,那就是线段树分治+可撤销的并查集的模板题
  2. 但是这是强制在线,但是这是虚伪的强制在线就是,每次个操作最多有两种的结果。
    l s t = { 0 , 1 } lst=\{0,1\} lst={0,1}, 最多也就 2 × m 2\times m 2×m个操作
  3. 就是我们有条有若干段存在的时间,我们插进线段树里面,用线段树去维护撤销顺序
  4. 首先我们先把两种结果都插进线段树里面,注意线段树分治本质是一个半在线算法
  5. 严格来说我们一开始只是把操作给划分成 l o g log log块,但是没有调用并查集
  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) { // 插销dsu
			auto 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;
}

标签:dsu,int,fy,线段,分治,离线,fx,ch
来源: https://blog.csdn.net/weixin_45630722/article/details/120555879

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有