【题目描述】:
有一副牌,由 N 张卡片组成,卡片上写着从 1 到 N 的整数(无重复)。
你将进行 N 次操作(编号 1∼N),每次操作的步骤如下:
- 你将得到一张卡片,设 X 是写在上面的整数。
- 观察桌上已有的,每个牌堆最上面卡片上的数字,找到大于或等于 X,且最小的,将 X 正面朝上放在这一牌堆的最上面。如果找不到这样的牌堆,则用 X 单独建立一个牌堆。
- 当某个牌堆有 K 张牌时,将这个牌堆全部拿走,并在每张牌上记录拿走时的操作编号。
【输入描述】:
第一行两个正整数 N 和 K;
第二行是按照操作次序,你将得到的卡片上的数字。
【输出描述】:
输出 N 行,第 i 行,输出数字 i 被拿走的操作编号。
【样例输入1】:
5 2
3 5 2 1 4
【样例输出1】:
4
3
3
-1
4
【样例1说明】:
P=(3,5,2,1,4),K=2。
在第一步中,写有 3 的牌面朝上放在桌子上,不叠在任何牌上。
在第二步中,写有 5 的牌面朝上放在桌子上,不叠在任何牌上。
在第三步中,写有 2 的牌面朝上叠放在写有 3 的牌上。
现在有一堆由 2 张牌组成,上面写着从上面开始的 2 和 3,这些牌被拿走。
在第 4 步中,写有 1 的牌面朝上叠放在写有 55 的牌上。
现在有一堆由 2 张牌组成,上面写着从上面开始的 1 和 5,这些牌被拿走。
在第五步中,写有 4 的牌面朝上放在桌子上,不叠在任何牌上。
写着 4 的牌直到最后都没有被拿走。
【样例输入2】:
15 3
3 14 15 9 2 6 5 13 1 7 10 11 8 12 4
【样例输出2】:
9
9
9
15
15
6
-1
-1
6
-1
-1
-1
-1
6
15
【时间限制、数据范围及描述】:
时间:1s 空间:256M
对于 30% 的数据:1≤K≤N≤1e4;
对于100% 的数据:1≤K≤N≤2×1e5;
分析与解:
用set
来维护桌子上的每叠牌。因为每叠牌被看到的只有最上面那张,所以每叠牌在set
里只用那最上面的牌来表示。利用set
递增排序的性质,我们按题意每次递牌的时候可用 lower_bound
二分去找最小的比 x 大或者等于的牌号,然后做盖住操作(set
删除那个牌号并插入新牌 x),如果找不到则将 x 直接插入set
。
除此之外,由于本题还要求每叠牌数目达到 K 时要被整叠删除,因此我们还必须开一个数组去维护某张牌对应的那叠牌的数目,每次在做set操作的同时去对这个数组做更新。另外,还需要一个链表顺序记录这一叠牌,方便在整叠删除时,给每个牌记录删除时间。
好了,贴上代码:
#include <bits/stdc++.h>
#define lc(a) (a)<<1
#define rc(a) (a)<<1|1
#define Mid int mid=l+r>>1
#define ll long long
#define Mod 1000000007
#define Max 1145141919
#define LLMax 9223372036854775807
using namespace std;
//I can All_Killed International Olmpiad in Informatics.
inline int in(){
char c=getchar();int f=1;int x;
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-')f=-1,c=getchar();
for(x=0;c>='0'&&c<='9';c=getchar())
x=(x<<3)+(x<<1)+(c^48);
return x*f;
}
template <typename T>
inline void in(T &x){
char c=getchar();int f=1;
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-')f=-1,c=getchar();
for(x=0;c>='0'&&c<='9';c=getchar())
x=(x<<3)+(x<<1)+(c^48);
x*=f;
}
const int N=2e5+5,M=1e3+5;
struct Top{
int v,id;
bool operator<(const Top &a)const{
return v<a.v;
}
};
set<Top> st;
vector<int> a[N];
int f[N];
int main(){
freopen("card.in","r",stdin);
freopen("card.out","w",stdout);
int n=in(),k=in(),cnt=0;
for(int i=1;i<=n;i++){
Top x;in(x.v),x.id=114514;
set<Top>::iterator it=st.lower_bound(x);
if(it==st.end()){
a[++cnt].push_back(x.v);
Top tmp=Top{x.v,cnt};
st.insert(tmp);
if(a[cnt].size()>=k){
st.erase(tmp);
for(auto j:a[cnt]) f[j]=i;
}
}
else{
int p=it->id;
Top tmp=Top{x.v,p};
st.erase(*it),st.insert(tmp),it=st.find(tmp);
a[p].push_back(x.v);
if(a[p].size()>=k){
st.erase(*it);
for(auto j:a[p]) f[j]=i;
}
}
}
for(int i=1;i<=n;i++)
printf("%d\n",f[i]==0?-1:f[i]);
return 0;
}