题目大意:有 n n n个队员,他们的能力值符合 n n n的排列,现在有两位教练要挑选队员,他们先选择当前队员里能力值最大的,然后选走该名队员左右各 k k k个队员,两个教练依次选取,求每个队员最终属于哪个教练.
解题思路:因为队员的能力值是不重复的,所以找当前能力值最大的,可以直接从 n n n遍历到 1 1 1,维护一下每个被选走的队员.这个题的关键在于,每次把队员选走之后如何去维护剩余的还存在的队员,直观的方法肯定是把已经选择的队员都删除,但是vector的删除复杂度很高.所以这个地方需要借用双向链表来将删除的复杂度降到 O ( 1 ) O(1) O(1).
#includeusing 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; }



