[20191005机房测试] Reverse
作者:互联网
小G有一个长度为n的01串T,其中只有TS=1,其余位置都是0。现在小G可以进行若干次以下操作:
· 选择一个长度为K的连续子串(K是给定的常数),翻转这个子串(左右翻转)
对于每个 i ∈ [1, n],小G想知道杓少要进行多少次操作使得Ti = 1
特别的,有m个禁止位置,你要保证在操作过程中 1 始终不在任何一个禁止位置上
原题面很坑……翻转指的是左右翻转而不是异或每个数……
考场上第一眼以为是Splay或者什么其他的算法,就去看T2T3了
结果T1一个爆搜就过了???
代码:
#include<bits/stdc++.h>
#define inf 1234567890
#define N 100005
using namespace std;
int n,K,m,S,x;
int L[N],R[N],dis[N];
template<class T>inline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
bool vis[N];
queue<int> q;
void bfs()
{
q.push(S);
vis[S]=1;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=max(1,x-K);i<=min(x,n-K);i++)
{
int t=K-x+(i<<1);
if(t>x)break;
if(!vis[t]&&dis[t]!=-1)
{
vis[t]=1;
dis[t]=dis[x]+1;
q.push(t);
}
if(dis[t]!=-1)i=max(i,(x+R[t]-K)>>1);
L[t]=min(L[t],K-x+max(1,x-K)*2);
R[t]=max(R[t],K-x+min(x,n-K)*2);
}
for(int i=min(x,n-K);i>=max(1,x-K);i--)
{
int t=K-x+(i<<1);
if(t<=x)break;
if(!vis[t]&&dis[t]!=-1)
{
vis[t]=1;
dis[t]=dis[x]+1;
q.push(t);
}
if(dis[t]!=-1)i=min(i,(x+L[t]-K)>>1);
L[t]=min(L[t],K-x+max(1,x-K)*2);
R[t]=max(R[t],K-x+min(x,n-K)*2);
}
}
}
int main()
{
freopen("reverse.in","r",stdin);
freopen("reverse.out","w",stdout);
read(n);read(K);read(m);read(S);
K--;
for(register int i=1;i<=N-5;++i) dis[i]=inf;
dis[S]=0;
for(register int i=1;i<=n;++i) L[i]=R[i]=i;
while(m--)
{
read(x);
dis[x]=-1;
}
bfs();
for(register int i=1;i<=n;++i)
{
if(dis[i]==inf) printf("-1 ");
else printf("%d ",dis[i]);
}
return 0;
}
标签:Reverse,20191005,min,int,max,read,机房,翻转,dis 来源: https://www.cnblogs.com/tqr06/p/11625392.html