题解 [ABC279E] Cheating Amidakuji

曾经总结过一类分治套路,没想到竟然派上用场了。

这种每个操作依次缺席的问题可以通过分治来解决。设 solve(l, r) 表示缺席的操作在 [l,r] 之间时求出它们的答案。

mid=l+r2,考虑将区间 [l,r] 划分为两个区间 [l,mid],[mid+1,r]。对于区间 [l,mid],可以知道区间 [mid+1,r] 的操作一定是执行了的。因此,在递归求解 [l,mid] 的时候,我们遍历 [mid+1,r] 的每一个操作,统计它对答案的影响。反之亦然。

本题中要注意操作执行的顺序问题。

由主定理易证复杂度为 T(m)=2T(m2)+Θ(m)=Θ(mlogm)

// Problem: E - Cheating Amidakuji
// Contest: AtCoder - TOYOTA SYSTEMS Programming Contest 2022(AtCoder Beginner Contest 279)
// URL: https://atcoder.jp/contests/abc279/tasks/abc279_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(int x=(y);x<=(z);x++)
#define per(x,y,z) for(int x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;
const int N = 2e5+5;

int n, m, a[N], p[N], pos[N], ans[N];
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
void swp(int i) {
	int x = p[i], y = p[i+1];
	swap(p[i], p[i+1]);
	swap(pos[x], pos[y]);
}
void calc(int& i) {i = pos[i];}
void solve(int L, int R, int now) {
	if(L == R) {
		ans[L] = now;
		return;
	}
	int M = (L + R) >> 1;
	{
		solve(L, M, now);
		rep(i, M+1, R) swp(a[i]);
		rep(i, L, M) calc(ans[i]);
		per(i, R, M+1) swp(a[i]);
	}
	{
		rep(i, L, M) swp(a[i]);
		calc(now);
		per(i, M, L) swp(a[i]);
		solve(M+1, R, now);
	}
}

int main() {
	scanf("%d%d", &n, &m);
	rep(i, 1, m) scanf("%d", &a[i]);
	rep(i, 1, n) p[i] = pos[i] = i;
	solve(1, m, 1);
	rep(i, 1, m) printf("%d\n", ans[i]);
	return 0;
}
posted @   rui_er  阅读(168)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2021-11-27 题解 CF895C 【Square Subsets】
点击右上角即可分享
微信分享提示