1. 程式人生 > >[2016北京集訓測試賽(五)]打地鼠-[思考題]

[2016北京集訓測試賽(五)]打地鼠-[思考題]

pri scrip name bsp 判斷 只需要 分享圖片 live src

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北京集訓測試賽(五)]打地鼠-[思考題]