E. Two Teams (模拟)

版权声明:转载注明下出处就行了。 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;
}

猜你喜欢

转载自blog.csdn.net/LJD201724114126/article/details/89361537