题目链接:http://codeforces.com/contest/1154/problem/E
题目大意:给你一个数组,两队教练会相间隔的从中选一些人,每次都会从未被选择的人中选择最大的那个,并将他左手边k个和右手边k个带走。问你最后每个人属于的教练编号。
很明显,这题需要我们动态地从数组中删除一段已被选择的人,如果暴力遍历已被选择的人必定超时(n<=1e5且k<=1e5)
所以可以很自然的想到利用数组链表进行删除操作。
用一个优先队列维护每个人,从大到小的选,选一个就将他和旁边2*k个人加入另一个队列中,一个个把他们都删除掉。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct Node{
int w,index;
Node(int _w,int _index):w(_w),index(_index){}
bool operator < (const Node& rhs)const{
return w<rhs.w;
}
};
const int maxn=200000+50;
int lef[maxn];
int rig[maxn];
int a[maxn];
int vis[maxn];
void dfs(){
}
priority_queue<Node>Q;
int main(){
int n,k;
while(scanf("%d%d",&n,&k)!=EOF){
memset(lef,0,sizeof(lef));
memset(rig,0,sizeof(rig));
memset(vis,0,sizeof(vis));
while(Q.size())Q.pop();
a[0]=0;a[n+1]=n+1;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
Q.push(Node(a[i],i));
lef[i]=i-1;
rig[i]=i+1;
}
int cmd=1;
while(Q.size()){
Node u=Q.top();Q.pop();
if(vis[u.index])continue;
queue<Node>q;
int cnt=k+1;
int now=u.index;
while(cnt>0&&now!=0){
q.push(Node(a[now],now));
now=lef[now];
cnt--;
}
cnt=k+1;
now=u.index;
while(cnt>0&&now!=n+1){
q.push(Node(a[now],now));
now=rig[now];
cnt--;
}
//rig[lef[u.index]]=rig[u.index];
//lef[rig[u.index]]=lef[u.index];//删除点u
//vis[u.index]=cmd;
while(q.size()){
Node x=q.front();q.pop();
//删除节点x
if(!vis[x.index]){
rig[lef[x.index]]=rig[x.index];
lef[rig[x.index]]=lef[x.index];
vis[x.index]=cmd;
}
}
cmd=cmd==1?2:1;
}
for(int i=1;i<=n;i++){
printf("%d",vis[i]);
}
printf("\n");
}
return 0;
}