H-subseq
题意:稍微转化一下题意就可以发现这题问的其实就是a序列中字典序第k大的递增子序列.
为了解决这道题,我们可以定义一个表示从i到后面的所有的递增自序列个数的总和,这个用树状数组就可以很简单的处理出来,但是要注意的是,这题的N的范围为5e5,那么dp[1]在极端情况下比如a本身就是一个递增序列的时候,肯定会爆long long
这个时候就要对树状数组稍作处理,因为k最大也只有1e18,所以我们将dp的最大值限定为1e18就够了
在处理出dp之后,我们从左往右找,假设我们目前已经取了m个数字,第m个数字为x,那么我们就要保证对于下一个取的数字j总是存在a[x]<a[j].
只要对于i位置dp[i]>=k,那么这个i肯定是我们要取的位置,否则更新k=k-dp[i]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
int a[maxn],b[maxn];
int sc[maxn];
ll bit[maxn];
ll dp[maxn];
int ans[maxn];
int lowbit(int x)
{
return x&-x;
}
void add(int x,ll v)
{
while(x)
{
bit[x]+=v;
if(bit[x]>1e18) bit[x]=1e18;
x-=lowbit(x);
}
}
ll sum(int x)
{
ll res=0;
while(x<maxn) res+=bit[x],res=min(res,1000000000000000000ll),x+=lowbit(x);
return res;
}
int main()
{
int n;
ll k;
scanf("%d%lld",&n,&k);
for(int i=1; i<=n; i++) scanf("%d",&a[i]),b[i]=a[i],bit[i]=0;
sort(b+1,b+n+1);
int pos=unique(b+1,b+n+1)-b;
for(int i=1; i<=n; i++) sc[i]=lower_bound(b+1,b+pos+1,a[i])-b;
dp[n]=1;
add(sc[n],1);
for(int i=n-1; i>=1; i--)
{
dp[i]=sum(sc[i]+1)+1;
add(sc[i],dp[i]);
}
int p=0;
for(int i=1; i<=n; i++)
{
if(k<=0) break;
if(a[i]>a[ans[p]])
{
if(k<=dp[i]) ans[++p]=i,k--;
else k-=dp[i];
}
}
if(k) return printf("-1\n")*0;
printf("%d\n",p);
for(int i=1; i<=p; i++) printf("%d ",ans[i]);
printf("\n");
}