牛客多校第五场 H subseq (线段树)

链接: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. 1<=b[i]<=n

  2. b[i]<b[i+1] for every i between 1 and m-1

  3. a[b[i]] < a[b[i+1]] for every i between 1 and m-1

  4. 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;
}

猜你喜欢

转载自blog.csdn.net/Lee_w_j__/article/details/81381859