题解 [ABC279E] Cheating Amidakuji

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

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

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

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

由主定理易证复杂度为 \(T(m)=2T(\frac{m}{2})+\Theta(m)=\Theta(m\log m)\)

// 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 @ 2022-11-27 09:00  rui_er  阅读(162)  评论(2编辑  收藏  举报