[2016北京集训测试赛]打地鼠-[思考题]

Posted coco-night

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[2016北京集训测试赛]打地鼠-[思考题]相关的知识,希望对你有一定的参考价值。

Description

技术分享图片

Solution

我们先只考虑一只地鼠的情况,依题意得,在某一个时刻该地鼠的可能停留位置是一个公差为2的等差数列。我们设这个等差数列的两端为[L,R]。则如果区间[L+1,R-1]的格子被打实际上是不会影响L和R的(列一个等差数列实际模拟一下就发现啦)。而如果格子L被打,则L+2;如果格子R被打,则R-2。打了格子后,别忘了L--,R++。

嗯根据以上性质,我们可以知道,地鼠1,3,5,7,9...的L是非递减的,地鼠2,4,6,8,10...的L也是非递减的。

然后看一下数据范围,初步判定时间复杂度为线性的。也就是说,我们要在O(1)时间内判断地鼠们的L有多少个和当前被打格子x相等。这个时候,奇偶性相同的地鼠L是非递减这个性质就很重要了。我们记录数组_l,_l[i]=x表示从第x只地鼠开始,往后所有与x奇偶性相同的地鼠的L会>=i。那地鼠们的L--怎么处理呢?我们把数组全部强行挪一位啊(可以用指针操作)。

 

对于数组_r,_r[i]=x表示从第x只地鼠开始,往前所有与x奇偶性相同的地鼠的R会<=i。处理方式和性质同上。

哦对了,记得处理死去的地鼠。只有地鼠的L和R同时被打中,地鼠才会死亡。我们只需要查询一下数组_l和_r就可以判断出有哪些地鼠死亡。由于死亡的地鼠应该是一个区间,可以差分。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1000010;
int n,m,x;
int _l[N<<2],*p_l=_l+N,l[N],L;
int _r[N<<2],*p_r=_r+N,r[N],R;
int not_alive[N<<2];
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) p_l[i]=p_r[i]=i;
    p_l[0]=1;p_r[n+1]=n;
    for (int i=1;i<N;i++) p_l[n+i]=n+1;
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&x);
        p_l[x+2]=p_l[x];L=p_l[x];
        p_r[x-2]=p_r[x];R=p_r[x];
        if (L<=R) not_alive[L]++,not_alive[R+2]--;
        p_l++;p_l[2]=p_l[0];
        p_r--;p_r[n-1]=p_r[n+1];
    }
    for (int i=1;i<=n;i++)
        for (int j=p_l[i];j<p_l[i+2];j+=2) l[j]=i;
    for (int i=n;i;i--)
        for(int j=p_r[i];j>p_r[i-2];j-=2) r[j]=i;
    for (int i=3;i<=n;i++) not_alive[i]+=not_alive[i-2];
    for (int i=1;i<=n;i++)
        not_alive[i]?printf("0 "):printf("%d ",(r[i]-l[i])/2+1);
}

 

以上是关于[2016北京集训测试赛]打地鼠-[思考题]的主要内容,如果未能解决你的问题,请参考以下文章

2016北京集训测试赛(十七)- 小结

2016北京集训测试赛river

2016北京集训测试赛直径

2016北京集训测试赛 crash的数列

2016北京集训测试赛azelso(unfinished)

[2016北京集训测试赛]azelso-[概率/期望dp]