• 8月7日假期集训T3


    题意学长给的挺详细的了,就不解释了......

    在学长的课件里面给出了很多的做法,这里就只说一下学长最后说的可以过的方法吧。

    对于数列中的每一个‘1’,我们都可以用一个长度为T的数组来记录每一个的行动状态,即用‘1’来表示向左移动一位,用‘0’来表示静止不动(就是其前面有'1'挡路啦),例如数列0001,T=3时里面那个1的运动状态就可以表示为111(即向左移动3位),现在我们考虑先把样例里面每一个的1的运动状态都弄一下,

    原数组:1 0 0 1 0 1 1 1 0 1    T=3

    运动状态(表示从左到右的每一个‘1’):000 ; 110 ; 111 ; 011 ; 001 ; 101。

     发现了什么没有,是不是我们先假设最初数组为000,之后我们每遇到一个‘1’,都在原数组的基础上先右移一位,再在前面插入一个‘0’,每遇到一个‘0’,都是把数组里面的第一个‘0’变为了1。其实对于这两条我们可以这样理解,对于我们扫到的一个‘1’,可能都会阻挡之后的‘1’前进的步伐,每遇到一个‘0’,就相当于后面的‘1’都可以比前面的‘1’多前进一步。相隔数个‘0’的两个‘1’,它们在前面的‘1’没有阻拦的情况下前进的步伐一样,如果有前面有阻拦且后面的还可以走,它的最终位置就是在前面的点的后面,就是砍去了前面的运动状态的最后一步(前面的'1'导致的右移一位),并且对于前面走不动的情况下,后面的点还可以进行移动,就是我们的将‘1’变为‘0’的情况。相隔数个‘1’的两个‘1’,他们前进的区别就是后面的‘1’要在前面的阻挡都清空的情况下才可以走前面的'1'的路,即我们的右移并补‘0’的操作。

    这样我们剩下的问题就是维护那个队列了,我这里为方便下标修改每一个‘0’,用的是手模的deque,并且又用了一个deque来记录数列里面每个‘0’的位置,由于我们插入‘0’的操作只有向前插入‘0’,那么插入的‘0’的下标就是单调递减的,我们每次放‘0’就把‘0’的下标放入队首,队列里面的坐标就是单增的,我们每次修改从队首取出第一个‘0’的位置,用下标直接修改就可以啦~

    对于答案的统计,计算的同时求一下‘1’的个数,初坐标减去该个数就是最后的位置,记录一下就行了。

    (貌似好像STL的deque也可以下标修改,但juruo太菜了不会用QAQ)

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=3e6+10;
     4 int q[5000000],head,back; //512mb,数组随便开吧~
     5 deque<int>qq; //存‘0’的下标用
     6 int a[N],ans[N],tot;  //tot记录此时数列的‘1’的个数,最后该‘1’右移了tot位,用于统计答案
     7 int main(){
     8     int n,k;
     9     scanf("%d%d",&n,&k);
    10     head=3500000; back=head-1;
    11     for(int i=1;i<=k;++i){
    12         qq.push_back(back+1); //先存一下初始状态
    13         q[++back]=0;
    14     }
    15     for(int i=1;i<=n;++i){
    16         scanf("%d",&a[i]);
    17         if(a[i]){
    18             ans[i-tot]=1;  //记录答案
    19             if(q[back]) tot--;  //进行pop队尾
    20             else{
    21                 if(!qq.empty())
    22                     qq.pop_back();
    23             }
    24             back--;
    25             q[--head]=0;
    26             qq.push_front(head); //push新的‘0’的下标
    27         }
    28         else{
    29             if(!qq.empty()){
    30                 q[qq.front()]=1;
    31                 qq.pop_front();
    32                 tot++;
    33             }
    34         }
    35     }
    36     for(int i=1;i<=n;++i)  //输出答案
    37         printf("%d ",ans[i]);
    38     puts("");
    39     return 0;
    40 }
    View Code
  • 相关阅读:
    录屏软件 OBS Studio
    ubuntu安装以及美化
    win10系统软件安装列表
    GNSS数据的弱点
    理解TomoDD生成的地壳模型的格式
    acrobat DC install
    matlab平行运算 parrelpool
    写申请地震台网数据的申请表
    强震动数据的网站
    visual studio各个版本的key
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/13453677.html
Copyright © 2020-2023  润新知