牛客网暑期ACM多校训练营(第五场)H. subseq 树状数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35406909/article/details/81370130

Problem H. subseq

Input file: standard input
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] < 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;
}

猜你喜欢

转载自blog.csdn.net/sinat_35406909/article/details/81370130
今日推荐