• BZOJ5484: [Usaco2018 Dec]Sort It Out


    5484: [Usaco2018 Dec]Sort It Out

    https://www.lydsy.com/JudgeOnline/problem.php?id=5484

    Sol.

    考虑没有在被喊叫集合中的点,他们一定是上升的。

    那么最小的集合大小就是n-最长上升子序列长度。

    对于第二问,有个转化:因为给出的是排列,求第k小的集合相当于求第k大的最长上升子序列。

    那么可以记f[i]表示以i为头的最长上升子序列长度,g[i]表示方案数,转移时一起转移。

    用个vector存最长上升子序列长度为i的开头有哪些,然后从大到小贪心取。

    有个技巧:树状数组可以反着用!

    我们要把1~x取Max,查询x~n的最小值。

    那么可以

    for(int i=x;i;i-=i&-i)tr[i]=max(tr[i],v)

    for(int i=x;i<=n;i+=i&-ii) sum=max(tr[i],sum)

    画个图看看似乎只有取Max可以用

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define ll long long
    #define maxn 100005
    #define inf 1e18
    using namespace std;
    int n,f[maxn],a[maxn],tr[maxn],v,fl[maxn],cnt,p[maxn],ans[maxn];
    ll g[maxn],k,way,w[maxn];
    vector<int>G[maxn];
    void Add(ll &x,ll y){
        if(inf-y<x)x=inf;
        else x+=y;
    }
    void ask(int i,int p){
        for(;i<=n;i+=i&-i){
            if(tr[i]>v)v=tr[i],way=w[i];
            else if(tr[i]==v)Add(way,w[i]);
        }
    }
    void add(int i){
        for(;i;i-=i&-i){
            if(v>tr[i])tr[i]=v,w[i]=way;
            else if(v==tr[i])Add(w[i],way);
        }
    }
    bool cmp(int a,int b){return a>b;}
    int main(){
        cin>>n>>k;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),p[a[i]]=i;
        for(int i=n;i>=1;i--){
            v=0,way=0;
            ask(a[i],1);
            v++;f[i]=v,g[i]=way;
            if(f[i]==1)g[i]=way=1;
            add(a[i]);
            G[f[i]].push_back(a[i]);
        }
        for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end(),cmp);
        int Max=0,mp=0;
        for(int i=n;i>=1;i--){
            for(int j=0;j<G[i].size();j++){
                if(G[i][j]<Max)continue;
                int pl=p[G[i][j]];
                if(pl<mp)continue;
                if(g[pl]>=k){
                    fl[pl]=1;Max=max(Max,G[i][j]);mp=max(mp,pl);
                    break;
                }
                k-=g[pl];
            }
        }
        cnt=0;
        for(int i=1;i<=n;i++)if(!fl[i])ans[++cnt]=a[i];
        sort(ans+1,ans+cnt+1);
        printf("%d
    ",cnt);
        for(int i=1;i<=cnt;i++)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    Software_programming_automation_selenium
    Software_programming_EnterpriseArch_ServiceWithSingleTonFactory
    web-bootstrap-button
    Software--C#--grammer_Delegate--Event
    Software_C#_grammer_Deletegate--Strategy
    Software--BigData--StreamingData
    线程死锁和递归锁
    同步锁Lock(互斥锁)
    GIL计算python 2 和 python 3 计算密集型
    什么是python的全局解释锁(GIL)
  • 原文地址:https://www.cnblogs.com/liankewei/p/11809805.html
Copyright © 2020-2023  润新知