码迷,mamicode.com
首页 > 其他好文 > 详细

[20191005机房测试] Reverse

时间:2019-10-05 20:09:58      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:res   lin   现在   out   eve   inf   get   bre   open   

小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;
}

[20191005机房测试] Reverse

标签:res   lin   现在   out   eve   inf   get   bre   open   

原文地址:https://www.cnblogs.com/tqr06/p/11625392.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!