题解 Reverse
考场上卡常过了……但可以被 \(k \in [45000, 55000]\) 且 \(k\) 为偶数的数据卡到1.4s左右
首先有个简单的BFS模拟思路
发现它合法的翻转半径是可以算出来的
所以这里枚举的边数可以优化,就可以卡过
至于正解,有一个 \(O(n)\) 的链表做法
发现我们实际上能访问到的点是一个区间内所有的奇/偶数点
考虑优化这个顺序访问过程
那就把整个数列存成链表,每个点指向下一个与当前点奇偶性相同且未被访问过的点
然后每访问一个区间,我们将这个区间内的点都指向右端点所指向的点
然后就没有了,每次在链表上顺序遍历就好
或者说这是路径压缩的并查集……无所谓啦
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define reg register int
#define fir first
#define sec second
#define make make_pair
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k, m, s;
int ans[N];
bool vis[N];
queue< pair<int, int> > q;
inline int max(int a, int b) {return a>b?a:b;}
inline int min(int a, int b) {return a<b?a:b;}
namespace force{
void solve() {
ans[s]=0; vis[s]=1;
q.push(make(s, 0));
pair<int, int> u;
const int mik=k>>1, eps=(k&1);
while (q.size()) {
u=q.front(); q.pop();
for (reg i=min(mik, n-u.fir+1-eps-mik),v,lim=max(0, mik-u.fir); i>lim; --i) {
v = u.fir+i*2-1+eps;
if (!vis[v]) {
ans[v]=u.sec+1;
vis[v]=1;
q.push(make(v, u.sec+1));
}
}
for (reg i=min(mik, u.fir-eps-mik),v,lim=max(1, u.fir+mik-n); i>=lim; --i) {
v = u.fir-i*2+1-eps;
if (!vis[v]) {
ans[v]=u.sec+1;
vis[v]=1;
q.push(make(v, u.sec+1));
}
}
}
for (reg i=1; i<=n; ++i) printf("%d ", ans[i]);
printf("\n");
exit(0);
}
}
namespace task{
int nxt[N];
void solve() {
ans[s]=0; vis[s]=1;
q.push(make(s, 0));
for (int i=n; i; --i)
if (i+2>n) nxt[i]=-1;
else if (vis[i]) nxt[i]=i+2;
else nxt[i]=i+2;
pair<int, int> u;
const int mik=k>>1, eps=(k&1);
while (q.size()) {
u=q.front(); q.pop();
//cout<<"u: "<<u.fir<<' '<<u.sec<<endl;
int s, t, si, ti;
si=max(1, mik-u.fir+1), ti=min(mik, n-u.fir+1-eps-mik);
if (si<=ti) {
s=u.fir+si*2-1+eps, t=u.fir+ti*2-1+eps;
for (int i=s,to; ~i&&i<=t; i=to) {
//assert(!vis[i]);
to=nxt[i];
if (!vis[i]) {
ans[i]=u.sec+1;
vis[i]=1;
q.push(make(i, u.sec+1));
}
nxt[i]=nxt[t];
}
}
si=max(1, u.fir+mik-n), ti=min(mik, u.fir-eps-mik);
if (si<=ti) {
s=u.fir-ti*2+1-eps, t=u.fir-si*2+1-eps;
//cout<<"st: "<<s<<' '<<t<<endl;
for (int i=s,to; ~i&&i<=t; i=to) {
//assert(!vis[i]);
to=nxt[i];
if (!vis[i]) {
ans[i]=u.sec+1;
vis[i]=1;
q.push(make(i, u.sec+1));
}
nxt[i]=nxt[t];
}
}
if (s>2) nxt[s-2]=nxt[t];
}
for (reg i=1; i<=n; ++i) printf("%d ", ans[i]);
printf("\n");
//cout<<"nxt: "; for (int i=1; i<=n; ++i) cout<<nxt[i]<<' '; cout<<endl;
exit(0);
}
}
signed main()
{
memset(ans, -1, sizeof(ans));
n=read(); k=read(); m=read(); s=read();
for (reg i=1; i<=m; ++i) vis[read()]=1;
task::solve();
return 0;
}