链接:https://www.nowcoder.com/acm/contest/143/H
来源:牛客网
题目描述
Kanade has an array a[1..n] , she define that an array b[1..m] is good if and only if it satisfy the following conditions:
-
1<=b[i]<=n
-
b[i]<b[i+1] for every i between 1 and m-1
-
a[b[i]] < a[b[i+1]] for every i between 1 and m-1
-
m>0
Now you need to find the k-th smallest lexicographically good array.
输入描述:
The first line has two integer n,k
The second line has n integer a[i]
输出描述:
If there is no solution, just only output -1, else output two lines, the first line has an integer m, the second line has m integer b[i]
示例1
输入
复制
3 2
1 2 3
输出
复制
2
1 2
示例2
输入
复制
3 1000000000
1 2 3
输出
复制
-1
备注:
1<=n <= 5*10^5
1<=k<=10^(18)
1<=a[i]<=10^9
题目大意:给定一个n个数的序列,要你求出下标字典序第k小的严格单调递增子序列。
题目思路:我们可以考虑先维护出以第 i 个数为开头的严格单调递增子序列的数量,这个借助线段树或者树状数组即可以维护出来,只需要倒着插入即可,以第 i 个数为开头的序列的数量就是区间 [i+1,n] 内大于第 i 个数的子序列数量之和+1,。最后在按位考虑即,看以当前位为开头的子序列是否小于k,再逐位枚举即可。注意本题可能会爆long long 所以在维护线段树的时候要设置一个数量的上界。
具体实现看代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lowbit(x) x&-x
#define pb push_back
#define MP make_pair
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define fuck(x) cout<<"["<<x<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef vector<int> VI;
const int MX=5e5+5;
const int mod=998244353;
const int inf=0x3f3f3f3f;
const ll infll=1e18;
//head
int n,a[MX],N;
ll sum[MX<<2],num[MX],k;
void push_up(int rt){
sum[rt]=min(infll,sum[rt<<1]+sum[rt<<1|1]);
}
void update(int p,ll d,int l,int r,int rt){
if(l==r){
sum[rt]=min(infll,sum[rt]+d);
return;
}
int m=(l+r)>>1;
if(p<=m) update(p,d,lson);
else update(p,d,rson);
push_up(rt);
}
ll query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R) return sum[rt];
ll res=0;
int m=(l+r)>>1;
if(L<=m) res=min(infll,res+query(L,R,lson));
if(R>m) res=min(infll,res+query(L,R,rson));
return res;
}
VI has,ans;
int get_id(int x){
return lower_bound(has.begin(),has.end(),x)-has.begin()+1;
}
int main(){
scanf("%d%lld",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
has.pb(a[i]);
}
sort(has.begin(),has.end());
has.erase(unique(has.begin(),has.end()),has.end());
N=has.size();
for(int i=1;i<=n;i++) a[i]=get_id(a[i]);
for(int i=n;i>=1;i--){
num[i]=query(a[i]+1,N,1,N,1)+1;
update(a[i],num[i],1,N,1);
}
int flag=0,last=0;
for(int i=1;i<=n;i++){
if(a[i]>last){
if(num[i]<k) k-=num[i];
else{
ans.pb(i);last=a[i];
if(k==1){
flag=1;
break;
}k--;
}
}
}
if(!flag) puts("-1");
else{
int sz=ans.size();
printf("%d\n",sz);
for(int i=0;i<sz;i++)
printf("%d%c",ans[i],i==sz-1?'\n':' ');
}
return 0;
}