Problem - E - Codeforces
题目大意:有 n n n个队员,他们的能力值符合 n n n的排列,现在有两位教练要挑选队员,他们先选择当前队员里能力值最大的,然后选走该名队员左右各 k k k个队员,两个教练依次选取,求每个队员最终属于哪个教练.
解题思路:因为队员的能力值是不重复的,所以找当前能力值最大的,可以直接从 n n n遍历到 1 1 1,维护一下每个被选走的队员.这个题的关键在于,每次把队员选走之后如何去维护剩余的还存在的队员,直观的方法肯定是把已经选择的队员都删除,但是vector的删除复杂度很高.所以这个地方需要借用双向链表来将删除的复杂度降到 O ( 1 ) O(1) O(1).
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define syncfalse ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N = 2e5+5;
bool use[N];
struct node{
int val, l, r;
}a[N];
int pos[N];
int ans[N];
int main(){
syncfalse
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n, k;
cin>>n>>k;
a[0].l=0,a[n+1].r=n+1; //初始化链表的边界很关键
for (int i = 1; i <= n; ++i){
cin>>a[i].val;
pos[a[i].val]=i;
a[i].l=i-1,a[i].r=i+1;
}
int now = 1;
for (int i = n; i >= 1; --i){
if (use[i])continue;
int tar = pos[i];
int val = a[tar].val;
ans[tar]=now;use[val]=true;
int tem = k;
int l = tar, r = tar;
while(tem){
l=a[l].l;
if (l==0)break;
ans[l]=now;
int val=a[l].val;
use[val]=true;
tem--;
}
tem=k;
while(tem){
r=a[r].r;
if (r==n+1)break;
ans[r]=now;
int val = a[r].val;
use[val]=true;
tem--;
}
l=a[l].l;
r=a[r].r;
a[r].l=l;
a[l].r=r;
if (now==1)now=2;
else now=1;
}
for (int i = 1; i <= n; ++i)cout << ans[i];
return 0;
}