曾经总结过一类分治套路,没想到竟然派上用场了。
这种每个操作依次缺席的问题可以通过分治来解决。设 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;
}
标签:Cheating,int,题解,rep,mid,pos,Amidakuji,swp,now
From: https://www.cnblogs.com/ruierqwq/p/abc279e.html