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

本文介绍了一种在线处理动态加边删边问题的高效算法,利用线段树维护撤销顺序,通过并查集快速合并操作,解决了O(n^2)的时间复杂度问题。主要关注如何在限制操作次数的情况下,实现对边连接状态的快速查询和更新。
摘要由CSDN通过智能技术生成

题目链接


题目大意

在这里插入图片描述


解题思路:

我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是 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;
}
### 回答1: "No-show-forced-updates"是指用户在不强制进行更新的情况下选择不更新软件或系统。 在计算机或移动设备上,经常会有软件或系统更新的提示。这些更新通常包含了修复漏洞、增强功能或解决问题的补丁。然而,有些用户可能因为各种原因选择不进行更新。 首先,一个可能的原因是用户担心更新过程会导致问题出现或者不兼容自己的设备和应用程序。他们担心更新后可能会出现错误,导致系统崩溃或应用程序无法正常使用。因此,他们选择不更新,以避免潜在的麻烦。 此外,一些用户可能没有足够的空间来安装更新。对于一些老旧设备或存储空间受限的设备,软件或系统更新可能会占用大量的存储空间,而用户无法或不愿为此进行空间的释放。 另外,个人偏好也是原因之一。有些用户可能对更新后的界面或功能不满意,而选择保持旧版本的软件或系统。他们可能习惯了当前版本的操作方式,或对新的界面设计没有兴趣。 然而,不进行软件或系统更新也存在一些风险。不更新可能会意味着用户错过了修复漏洞、增强安全性和性能的机会。而且,对于一些应用程序来说,不进行更新可能会导致其无法在后续时间内正常运行。 总之,"no-show-forced-updates"反映了用户在不被强制进行更新的情况下选择不更新的行为。这种行为可能是由于担心问题出现、存储空间限制或个人偏好等因素造成的。用户在权衡利弊后,根据自身需求和风险来做出决策。 ### 回答2: --no-show-forced-updates是一个命令行选项,用于禁止强制更新。在一些软件或操作系统中,强制更新是指强制用户接受更新并进行安装,即使用户不想进行更新或希望延迟更新。通过使用--no-show-forced-updates选项,用户可以自行决定是否接受强制更新。 这个选项的存在是为了满足一些用户对隐私或安全的关注,或者因为他们不希望运行可能会引入新问题或不稳定的软件版本。通过使用--no-show-forced-updates,用户可以继续使用当前版本的软件而不会被迫接受新的更新。 然而,需要注意的是,禁用强制更新可能存在一些潜在的风险。新的更新通常是为了修复漏洞、增强功能、提高性能或解决其他问题而发布的。如果用户选择不接受这些更新,他们可能会错过重要的安全补丁或新功能。因此,在决定是否禁用强制更新时,用户需要谨慎权衡安全性和稳定性与个人对隐私的考虑。 总体而言,--no-show-forced-updates是一个能够让用户在一定程度上控制软件或操作系统更新的选项。用户可以根据自己的需求和偏好决定是否禁用强制更新,但需要明智地平衡安全性、稳定性和隐私权。 ### 回答3: --no-show-forced-updates 是一个指令或选项,用于禁止软件或操作系统自动强制更新。在不设置该选项的情况下,很多软件或操作系统会自动检查并安装最新版本的更新,这些更新可能包含修复漏洞、改进性能或增加新功能等。然而,有时候用户可能因为种种原因不希望立即安装这些更新,可能是因为更新内容不符合个人需求、担心更新会引起不稳定、担心可能破坏已有的配置或应用程序等。 通过设置 --no-show-forced-updates 选项,用户可以完全掌控自己的更新策略。这意味着软件或操作系统将不会自动弹出提示,要求用户安装更新,并且不会在后台下载和安装更新。用户可以按照自己的时间表,自行安装更新,或者选择不安装某个特定的更新。 然而,需要注意的是,禁止自动强制更新也可能带来一些风险。更新通常包含了修复重要的安全漏洞,当用户选择禁用自动更新时,可能会将自己的系统暴露在潜在的安全风险中。因此,建议用户在禁用自动更新之前,评估好自己的风险承受能力,并采取其他安全措施来保护自己的系统。 最后,用户可以通过撤销 --no-show-forced-updates 选项来恢复自动更新功能,以确保及时获取软件和操作系统的最新修复和功能更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值