zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:Reverse(模拟+暴力+剪枝)

    题目描述

      小$G$有一个长度为$n$的$01$串$T$,其中只有$T_S=1$,其余位置都是$0$。现在小$G$可以进行若干次以下操作:
      $ullet$选择一个长度为K的连续子串($K$是给定的常数),翻转这个子串。
      对于每个$i,iin[1,n]$,小$G$想知道最少要进行多少次操作使得$T_i=1$。特别的,有$m$个“禁止位置”,你需要保证在操作过程中$1$始终不在任何一个禁止位置上。


    输入格式

      从文件$reverse.in$中读入数据。
      第一行四个整数$n,K,m,S$。
      接下来一行$m$个整数表示禁止位置。


    输出格式

      输出到文件$reverse.out$中。
      输出一行$n$个整数,对于第$i$个整数,如果可以通过若干次操作使得$T_i=1$,输出最小操作次数,否则输出$−1$。


    样例

    样例输入1:

    6 2 0 1

    样例输出1:

    0 1 2 3 4 5

    样例输入2:

    10 4 3 3
    2 5 10

    样例输出2:

    2 -1 0 1 -1 1 2 3 2 -1


    数据范围与提示

    对于所有数据,有$1leqslant nleqslant 10^5,1leqslant S,kleqslant n,0leqslant mleqslant n$。
    保证$S$不是禁止位置,但禁止位置可能有重复。
    $ullet Subtask1(24\%)$,$nleqslant 10$。
    $ullet Subtask2(22\%)$,$nleqslant 10^3$。
    $ullet Subtask3(3\%)$,$k=1$。
    $ullet Subtask4(8\%)$,$k=2$。
    $ullet Subtask5(43\%)$,没有特殊的约束。


    题解

    首先解释一下题意,翻转子串指的是将其左右颠倒,而不是异或……

    我也不知道为什么会理解错,老是死在语文……

    就是一道大模拟,正解用$set$维护,但是可以疯狂加剪枝,但是理论时间复杂度还是线性的,具体剪枝看代码吧,满眼都是泪哇……

    不过话说考试的时候看样例找规律能水到$11$分我也是满足了……

    时间复杂度:$Theta(n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n,K,m,S;
    bool vis[100001];
    int L[100001],R[100001];
    int dis[100001];
    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()
    {
    	scanf("%d%d%d%d",&n,&K,&m,&S);K--;
    	memset(dis,0x3f,sizeof(dis));dis[S]=0;
    	for(int i=1;i<=n;i++)L[i]=R[i]=i;
    	while(m--)
    	{
    		int x;scanf("%d",&x);
    		dis[x]=-1;
    	}
    	BFS();
    	for(int i=1;i<=n;i++)
    	{
    		if(dis[i]==0x3f3f3f3f)printf("-1 ");
    		else printf("%d ",dis[i]);
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    WinCMD color命令
    WinCMD if命令(批处理Dos 大于、小于、等于)
    WinCMD 常用命令
    AIFramework基本概念整理
    AICompiler动态shape编译框架
    深度学习编译与优化Deep Learning Compiler and Optimizer
    NNVM Compiler,AI框架的开放式编译器
    Tengine AIFramework框架
    Tvm一些基本技术
    北汽蓝谷和北汽新能源
  • 原文地址:https://www.cnblogs.com/wzc521/p/11623155.html
Copyright © 2011-2022 走看看