版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/89361537
题目链接:https://codeforces.com/contest/1154/problem/E
题意:给你n个人,每个人有一个值,现在有两个教练,每个教练要轮流从这n个人挑选队员,每次教练会挑选值最大的作为自己的学员,然后会在这个学员的左边挑选k个人作为自己的学员,在右边也挑选k个作为自己的学员。
题解:模拟。我们先标记下每个值出现的位置,然后从大到小开始。
再用数组 L[]表示当前位置i的左边的起始点,R[]表示当前位置右边的起始点。
我之前是直接逐个判断的,遇到已经被挑选过的,我直接跳2*k个,因为只要他被选上了,那么就一定有连续的2*k个(边界除外)。当时过了,早上醒来就被hack了。这样做很卡时间。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
typedef long long LL;
const LL mod=1e9+7;
int num[200010],ans[200010];
int pos[200010];
int L[200010],R[200010];
int vis[200010];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++)
{
scanf("%d",&num[i]);
vis[i]=0;
ans[i]=num[i];
pos[num[i]]=i;
L[i]=i-1; ///记录当前位置的左起始位置
R[i]=i+1;
}
sort(ans+1,ans+1+n);
int in=1;
for(int i=n; i>=1; i--)
{
int item=pos[ans[i]];
if(vis[item]) continue;
vis[item]=in;
int t=k;
int l=L[item];
while(t--&&l>=1)
{
vis[l]=in;
l=L[l];
}
int r=R[item];
t=k;
while(t--&&r<=n)
{
vis[r]=in;
r=R[r];
}
L[r]=l;
R[l]=r;
if(in==1) in=2;
else in=1;
}
for(int i=1; i<=n; i++)
printf("%d",vis[i]);
return 0;
}