E. Two Teams(双向链表模拟)

https://codeforces.com/problemset/problem/1154/E


题目描述

There are nn students standing in a row. Two coaches are forming two teams — the first coach chooses the first team and the second coach chooses the second team.

The ii -th student has integer programming skill a_iai​ . All programming skills are distinct and between 11 and nn , inclusive.

Firstly, the first coach will choose the student with maximum programming skill among all students not taken into any team, and kk closest students to the left of him and kk closest students to the right of him (if there are less than kk students to the left or to the right, all of them will be chosen). All students that are chosen leave the row and join the first team. Secondly, the second coach will make the same move (but all students chosen by him join the second team). Then again the first coach will make such move, and so on. This repeats until the row becomes empty (i. e. the process ends when each student becomes to some team).

Your problem is to determine which students will be taken into the first team and which students will be taken into the second team.

输入格式

The first line of the input contains two integers nn and kk ( 1 \le k \le n \le 2 \cdot 10^51≤k≤n≤2⋅105 ) — the number of students and the value determining the range of chosen students during each move, respectively.

The second line of the input contains nn integers a_1, a_2, \dots, a_na1​,a2​,…,an​ ( 1 \le a_i \le n1≤ai​≤n ), where a_iai​ is the programming skill of the ii -th student. It is guaranteed that all programming skills are distinct.

输出格式

Print a string of nn characters; ii -th character should be 1 if ii -th student joins the first team, or 2 otherwise.

题意翻译

Description

有 nn 个人站成一排,他们每个人都有一个能力值,能力值互不相同。

有两个教练,分别是 11 队教练和 22 队教练。由 11 队教练先挑,每次教练会将场上剩下的人中能力值最高的和他左右各 kk 个人从场上挑出,加入自己的队伍,然后由另一名教练再挑。

在挑选时如果一侧不足 kk 个人则将这些人都挑入队伍。

请求出每个人最终加入的是哪个队伍

Input

第一行是两个整数 n,~kn, k

下面一行是一个 11 到 nn 的排列,描述每个人的能力值

Output

输出一行一个字符串。如果第 ii 个人最终加入 11 队,则字符串第 ii 位为 11,否则为 22。

Limitation

1~\leq~k~\leq~n~\leq~2~\times~10^51 ≤ k ≤ n ≤ 2 × 105

Translated By @ 一扶苏一

输入输出样例

输入 #1复制

5 2
2 4 5 3 1

输出 #1复制

11111

输入 #2复制

5 1
2 1 3 5 4

输出 #2复制

22111

输入 #3复制

7 1
7 2 1 3 5 4 6

输出 #3复制

1121122

输入 #4复制

5 1
2 4 5 3 1

输出 #4复制

21112

思路:开始暴力想法是O(n)找到队里最大的,然后左扫右扫标记。

用双向链表优化。拿一个结构体记录值和下标然后根据值sort,sort完后从最大值去看是否被访问,未访问就通过双向链表的关系O(1)找下标标记同时更新下标相连关系。均摊O(n)复杂度

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+100;
typedef long long LL;
LL n,k,vis[maxn];
LL pre[maxn],nxt[maxn];
struct node{
	LL val,id;
}a[maxn];
bool cmp(node A,node B)
{
	return A.val>B.val;
}
void solve()
{
	for(LL i=1;i<=n;i++){
		cin>>a[i].val;a[i].id=i;
	}
	for(LL i=1;i<=n;i++){
		pre[i]=i-1;
		nxt[i]=i+1;
	}
	sort(a+1,a+1+n,cmp);
	LL flag=1;
	for(LL i=1;i<=n;i++)
	{
		if(!vis[a[i].id]){
			LL pos=a[i].id;
			LL js=k+1;//往前扩展 
			while(js&&!vis[pos]&&pos>=1)
			{
				vis[pos]=flag;
				js--;
				pos=pre[pos];
			}
			LL st=pos;//扩展到的前面的点 
			js=k;
			pos=nxt[a[i].id];
			while(js&&!vis[pos]&&pos<=n)
			{
				vis[pos]=flag;
				js--;
				pos=nxt[pos];
			}
			pre[pos]=st;
			nxt[st]=pos;
			if(flag==1) flag=2;
			else if(flag==2)flag=1;
		}	
	}
	for(LL i=1;i<=n;i++){
		cout<<vis[i];
	}
	cout<<endl;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  cin>>n>>k;
  solve();
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108457642
今日推荐