zoukankan      html  css  js  c++  java
  • 牛客网暑期ACM多校训练营(第五场)H-subseq 树状数组

    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

    题意:给出一个数组a,求的一个第k小且符合b[i]<b[i+1] a[b[i]]<b[b[i+1]]的序列
    思路:我们可以考虑每个点的贡献 如果 a序列为 1 2 3
    我们可以写出 1 ,1 2,1 3, 1 2 3 四种以1开头的符合题意的序列b
    分析下样例1:我们能的到如下序列b, 1, 1 2, 1 2 3,1 3, 2 , 2 3,3 字典序第2小 显然是1 2我们即可输出 1 2
    考虑我们怎么维护树状数组,我们离散化后,我们维护的是这个点能给其他点添加序列 比如3 能给1添加两次贡献,能 2添加1次 给3添加1次
    我们从a[n]遍历到a[1],我插入前需要查询此点的贡献。
    继续分析样例:
    3离散后也是,3,我们查询比3大的是否有贡献,3为第一个插入的数 贡献为它自己1 插入到树状数组
    继续 2离散后是2,我们查询比2大的是否有贡献,显然3之前我们已经插入了 ,此时2的贡献为1+1(3的贡献 插入到树状数组
    最后 1离散后是1,我们查询比1大的是否有贡献,显然2和3我们之前已经插入了,此时1的贡献为1+2(2的贡献)+1(3的贡献) 然后插入进去
    然后我们只需要慢慢求下标就好了,k>f[i](a[i]的贡献)我们就不需要用到a[i]这个点,k<=f[i]时我们就只要慢慢求出和a[i]构成的序列即可
    在维护的时候如果贡献大于1e18我们就只需要讲贡献改为1e18就行 k的取值最大1e18

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=6e5+10;
    const long long inf=1e18;
    ll a[maxn],f[maxn],tree[maxn],N;
    vector<ll> v;
    int getid(ll x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
    int lowbit(int x){return x&(-x);}
    void add(int x,ll val)
    {
        for(; x; x-=lowbit(x))
        {
            tree[x]+=val;
            if(tree[x]>=inf) tree[x]=inf;
        }
    }
    ll query(int x)
    {
        ll ans=0;
        for(; x<=N; x+=lowbit(x))
        {
            ans+=tree[x];
            if(ans>=inf) ans=inf;
        }
        return ans;
    }
    int main()
    {
        int n;
        ll k;
        scanf("%d %lld",&n,&k);
        for(int i=1; i<=n; i++)
        {
            scanf("%lld",&a[i]);
            v.push_back(a[i]);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        N=v.size();
        for(int i=n; i>=1; i--)
        {
            f[i]=query(getid(a[i])+1)+1;
            add(getid(a[i]),f[i]);
        }
        ll last=0;
        vector<int> V;
        for(int i=1; i<=n; i++)
        {
            if(k==0) break;
            if(a[i]>last)
            {
                if(k<=f[i])
                {
                    k--;
                    V.push_back(i);
                    last=a[i];
                }
                else
                {
                    k-=f[i];
                }
            }
    
        }
        if(k)
            return 0*puts("-1");
        printf("%d
    ",V.size());
        for(int i=0; i<V.size(); i++)
        {
            printf("%d%c",V[i]," 
    "[i==V.size()-1]);
        }
        return 0;
    
    }
    View Code



    PS:摸鱼怪的博客分享,欢迎感谢各路大牛的指点~
  • 相关阅读:
    asp.net Ctrl+回车提交
    Request.Form.Keys保存的是什么?
    让iframe子窗体取父窗体地址栏参数(querystring)
    Repeater在无数据记录时显示类似GridView空模板(EmptyDataTemplate)
    jQuery与javascript对照学习(获取父子前后元素)
    internet缓存Temp中的tmp文件
    C#反射遍历一个对象属性(小技巧)
    silverlight序列化反序列化,在c#其他程序反序列化
    Silverlight序列化反序列化(json.net)
    卸载oracle
  • 原文地址:https://www.cnblogs.com/MengX/p/9412965.html
Copyright © 2011-2022 走看看