Problem H. subseq
Output file: standard output
Time limit: 2 seconds
Memory limit: 256 mebibytes
Problem Description
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]
<
<
<script type="math/tex" id="MathJax-Element-1"><</script>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.
Input
The first line has two integer n,k
The second line has n integer a[i]
Output
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]
Sample Input | Sample Output |
---|---|
3 2 1 2 3 | 2 1 2 |
给出数列a,求出原数组下标字典序第k小的上升子序列。
利用树状数组逆序算出每个数开头时,上升子序列的个数。
这里要注意,因为个数可能达到无穷,所以需要把树状数组反向,或者把a数组取反。
之后枚举每一位的取舍,便可以得到答案。
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#include <assert.h>
#define pb push_back
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef pair<int,int> pp;
const int maxn=500005,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
const ld pi=acos(-1.0L);
int a[maxn],b[maxn],ans[maxn];
ll f[maxn],dp[maxn];
int lowbit(int a) {
return (a&(-a));
}
ll getsum(int tt,int n) {
ll sum=0;
for (int t=tt;t<=n;t+=lowbit(t))
sum=min(sum+f[t],llinf);
return sum;
}
void update(int tt,ll c,int n) {
int t=tt;
for (int t=tt;t;t-=lowbit(t))
f[t]=min(f[t]+c,llinf);
}
int main() {
ll n,k;
scanf("%lld%lld",&n,&k);
for (int i=1;i<=n;i++) {
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
ll m=unique(b+1,b+n+1)-b-1;
for (int i=1;i<=n;i++) {
a[i]=lower_bound(b+1,b+m+1,a[i])-b;
}
for (int i=n;i>=1;i--) {
dp[i]=getsum(a[i]+1,n)+1; //若两个getsum相减是不对的
dp[i]=min(dp[i],llinf);
update(a[i],dp[i],n);
}
if (k>getsum(1,n)) {
printf("-1\n");return 0;
}
m=0;
for (int i=1;i<=n;i++) {
if (a[i]<=a[ans[m]]) continue;
if (k<=dp[i]) {
k--;
ans[++m]=i;
} else {
k-=dp[i];
}
if (k==0) break;
}
printf("%lld\n",m);
for (int i=1;i<=m;i++) {
printf("%d ",ans[i]);
}
return 0;
}