Description
给出一个长度为 n n n的序列 a 1 , . . . , a n a_1,...,a_n a1,...,an,定义序列 b 1 , . . . , b m b_1,...,b_m b1,...,bm是好的当且仅当以下条件成立:
1. 1 ≤ b i ≤ n , 1 ≤ i ≤ m 1\le b_i\le n,1\le i\le m 1≤bi≤n,1≤i≤m
2. b i < b i + 1 , 1 ≤ i < m b_i<b_{i+1},1\le i<m bi<bi+1,1≤i<m
3. a b i < a b i + 1 , 1 ≤ i < m a_{b_i}<a_{b_{i+1}},1\le i<m abi<abi+1,1≤i<m
求所有好的 b b b序列中字典序第 k k k小的
Input
第一行输入两个整数 n , k n,k n,k,之后输入 n n n个整数 a 1 , . . . , a n a_1,...,a_n a1,...,an
( 1 ≤ n ≤ 5 ⋅ 1 0 5 , 1 ≤ k ≤ 1 0 18 , 1 ≤ a i ≤ 1 0 9 ) (1\le n\le 5\cdot 10^5,1\le k\le 10^{18},1\le a_i\le10^9) (1≤n≤5⋅105,1≤k≤1018,1≤ai≤109)
Output
输出字典序第 k k k小的好的 b b b序列,无解则输出 − 1 -1 −1
Sample Input
3 2
1 2 3
Sample Output
2
1 2
Solution
以 d p [ i ] dp[i] dp[i]表示以 i i i开头的满足条件的 b b b序列个数,那么有 d p [ i ] = 1 + ∑ i < j , a i < a j d p [ j ] dp[i]=1+\sum\limits_{i<j,a_i<a_j}dp[j] dp[i]=1+i<j,ai<aj∑dp[j],用树状数组维护 d p [ i ] dp[i] dp[i]的值,从后往前转移,每次把 d p [ i ] dp[i] dp[i]根据 a i a_i ai的值插入树状数组中,即可 O ( n l o g n ) O(nlogn) O(nlogn)得到 d p dp dp序列
之后从前往后考虑字典序第 k k k小的 b b b序列,假设第一位放 1 1 1,那么有 d p [ 1 ] dp[1] dp[1]种方案数,若 k ≤ d p [ 1 ] k\le dp[1] k≤dp[1],说明第一位确实是 1 1 1,进而考虑第二位的取值(注意:1.每次考虑当前位的取值必然要大于已经确定的前一位取值;2.由于确定完当前位后,后面的取值有空和非空两种情况,此时要将 k k k减一来去掉后面为空的情况,减完后若 k k k为 0 0 0说明后面确实为空,否则继续考虑后面位的取值),若 k > d p [ 1 ] k>dp[1] k>dp[1],说明第一位不是 1 1 1,那么 k = k − d p [ 1 ] k=k-dp[1] k=k−dp[1],表示有 d p [ 1 ] dp[1] dp[1]种字典序小的方案已经考虑了,下面考虑其他值放在第一位,以此类推,若考虑完所有元素 k k k仍然非 0 0 0则无解,否则已经确定的序列即为答案,时间复杂度 O ( n ) O(n) O(n)
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
ll INF=2e18;
#define maxn 500005
struct BIT
{
#define lowbit(x) (x&(-x))
ll b[maxn],n;
void init(int _n)
{
n=_n;
for(int i=1;i<=n;i++)b[i]=0;
}
void update(int x,ll v)
{
while(x<=n)
{
b[x]+=v;
b[x]=min(b[x],INF);
x+=lowbit(x);
}
}
ll query(int x)
{
ll ans=0;
while(x)
{
ans+=b[x];
ans=min(ans,INF);
x-=lowbit(x);
}
return ans;
}
}bit;
int n,a[maxn],h[maxn];
ll k,dp[maxn];
vector<int>ans;
int main()
{
scanf("%d%lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
h[i-1]=a[i];
}
sort(h,h+n);
int m=unique(h,h+n)-h;
bit.init(m);
for(int i=n;i>=1;i--)
{
a[i]=m+1-(lower_bound(h,h+m,a[i])-h+1);
dp[i]=bit.query(a[i]-1)+1;
dp[i]=min(dp[i],INF);
bit.update(a[i],dp[i]);
}
for(int i=1;i<=n;i++)
{
if(ans.size()>0&&a[i]>=a[ans[ans.size()-1]])continue;
if(k==0)break;
if(dp[i]>=k)
{
ans.push_back(i);
k--;
}
else k-=dp[i];
}
if(k)printf("-1\n");
else
{
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)
printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
}
return 0;
}