首页 > 其他分享 >P5156 [USACO18DEC] Sort It Out P 题解

P5156 [USACO18DEC] Sort It Out P 题解

时间:2023-10-25 19:55:17浏览次数:34  
标签:Sort typedef pil int 题解 long pair USACO18DEC

题意

有一个长度为 \(n\) 的排列 \(a_1,a_2,\cdots,a_n\),选出 \(\{1,2,\cdots,n\}\) 的一个子集,对这个子集中的数依次进行如下操作:

  • 设当前数为 \(v\),则若 \(a_v\) 大于 \(a_{v+1}\)(如果有的话),就交换。如果小于,则若 \(a_v<a_{v-1}\)(如果有的话),就交换。重复上述操作知道 \(a_{v-1}<a_v<a_{v+1}\) 为止。

求大小最小的能让 \(a\) 最后有序的子集中,字典序第 \(K\) 小的。

题解

首先,注意到对于一个子集进行操作等于把子集中的所有数都排到正确的位置。如果原数组最后有序,则所有子集之外的数一开始就是有序的。

答案为 \(n - \texttt{[the length of LIS]}\),第 \(K\) 小字典序的答案即为第 \(K\) 大字典序的 LIS。

考虑如何求这个东西。容易用树状数组计算出 \(i\) 开始的上升子序列的最大长度和最大长度的个数,然后从前往后通过 \(K\) 依次确定每一位即可。

时间复杂度 \(\mathcal{O(n\log n)}\),瓶颈在树状数组。

代码

#include <bits/stdc++.h>
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define per(i,j,k) for(int i=(j);i>=(k);i--)
#define pb push_back
#define mpr make_pair
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
const int N=1e5+10;
int n,a[N];
ll K;
pil dp[N];
vector<int> pos[N];
bool mark[N];
pil merge(pil x,pil y){
    if(x.first!=y.first)return max(x,y);
    return make_pair(x.first,min(K,x.second+y.second));
}
struct FenwickTree{
    pil tree[N];
    void update(int x,pil v){
        while(x>0){
            tree[x]=merge(tree[x],v);
            x-=x&-x;
        }
    }
    pil query(int x){
        pil res=make_pair(-1,0LL);
        while(x<=n){
            res=merge(res,tree[x]);
            x+=x&-x;
        }
        return res;
    }
}T;
int main(){
    scanf("%d%lld",&n,&K);
    rep(i,1,n){
        scanf("%d",a+i);
    }
    T.update(n+1,make_pair(0,1LL));
    int len=0;
    per(i,n,1){
        dp[i]=T.query(a[i]);
        dp[i].first++;
        len=max(len,dp[i].first);
        T.update(a[i],dp[i]);
        pos[dp[i].first].push_back(i);
    }
    printf("%d\n",n-len);
    int cur=0;
    per(t,len,1){
        reverse(pos[t].begin(),pos[t].end());
        for(auto v:pos[t]){
            if(dp[v].second>=K){
                mark[a[v]]=1;
                while(cur+1<v){
                    cur++;
                    dp[cur]=make_pair(0,0LL);
                }
                break;
            }
            K-=dp[v].second;
        }
    }
    rep(i,1,n){
        if(!mark[i]){
            printf("%d\n",i);
        }
    }
	return 0;
}

标签:Sort,typedef,pil,int,题解,long,pair,USACO18DEC
From: https://www.cnblogs.com/Jerry-Jiang/p/17787981.html

相关文章

  • CF1555D题解
    分析注意到字符集大小很小,那么很容易就会产生回文,那么合法序列的种类就会比较有限。思考对于不同长度而言合法序列的种类,显然长度为\(1\)时无回文,长度为\(2\)只要两个字符不同就无回文。尝试扩展到长度为\(3\)时的情况,显然\(s_1\neqs_2\),\(s_2\neqs_3\)。发现\(s......
  • P9669 [ICPC2022 Jinan R] DFS Order 2 题解
    P9669[ICPC2022JinanR]DFSOrder2题解简要题意给定一棵\(n\)个节点的树,根节点是\(1\)。从根节点开始深度优先搜索这一棵树,dfs序是在搜索过程中访问节点的顺序。对于每一个节点\(v\),你要给出有多少种不同的dfs序,使得\(v\)出现在第\(j\)个位置。答案对\(99824......
  • P9769 HUSTFC 2023 简单的加法乘法计算题 题解
    动态规划#单调队列Question给出一个\(x=0\)通过一些操作把\(x\)变成\(y\)。有两个集合\(A,B\)。\(A\)包含了\(n\)个元素,分别是\(1-n\)的所有正整数,集合\(B\)给出\(m\)个元素,可以进行一下函数选择\(A\)中的一个元素\(a\),令\(x\)加上\(a\)选择\(B\)......
  • CF1555B题解
    分析放桌子有两种放法,一种是上下放,一种是左右放,分别计算最小值取\(\min\)即可。注意到原题使用的是平面直角坐标系,于是将原图顺时针旋转\(90^{\circ}\),将下标表示方式与代码中下标的表示方式统一,相应的,左下角和右上角也变成了左上角和右下角。代码#include<iostream......
  • Kettle链接SqlServer+Jdk8 问题解决
     这两天要弄个ldap对接,客户端server2016,数据库那边winserver2008,数据库也是2008最开是链接出现类似这样的,更换了链接mssql的Jar版本,从12换到了6的老版本,没用。  后来更改网上提示的  C:\ProgramFiles\Java\jre-1.8\lib\security\java.security文件jdk.tls.......
  • B1024 题解
    本着10月杂题题解只记重量级的原则,再加上这个系列好久没更新了,搞一发。原题链接发挥还可以的一场,至少比csp-s发挥的好。T1智慧概率题,考场差点出来,30pts。T2简单计数题,之前几场都卡T2,终于出来一次,100pts。T3简单数据结构题,打的30pts暴力,但是有50pts。T4智慧......
  • CF1572F Stations 题解-Segment Tree Beats
    20231025CF1572FStations题解-SegmentTreeBeats吉司机线段树好题!!!CF3400。传送门Statement有\(n\)个广播站,第\(i\)个广播站高度为\(h_i\),范围为\(w_i\)。初始\(h_i=0,w_i=i\)。广播站\(i\)能向广播站\(j\)传递消息,当且仅当\(i\lej\lew_i\),且\(h_i>\max\lim......
  • 恨7不成妻题解
    恨7不成妻题解分析数位\(DP\)考虑题目中的两个条件,每一位不等于\(7\)直接枚举时把\(7\)排除,其他两种情况直接放在状态里。因为题目要求平方和,我们考虑每次加上一位(设加入的是第\(i\)位)时会发生什么设原平方和为\[\sum_{k=1}^ta_k^2\]加入一位\(p\)之后每个数......
  • P9771 HUSTFC 2023 排列排序问题 题解
    Question给出一个\(N\)个元素的排序\(a\),我们可以对排列进行一些操作将这个排列切割成若干个序列将其中一些序列翻转将这些序列连接起来得到一个新的排列需要让最后的排列有序Solution这个题的描述有点小问题理解应该是切一次,然后再反转合并,不可能会先合并再切再反转......
  • P9744 「KDOI-06-S」消除序列 题解
    @目录DesciptionSolutionCodeDesciption给定一个长度为\(i\)的序列\(v_1,v_2,\dots,v_n\),初始时所有元素的值都为\(1\)。对于下标\(i\)有\(3\)种操作:将\(v_1,v_2,\dots,v_i\)的值变为\(0\),费用是\(a_i\)。将\(v_i\)的值变为\(0\),费用是\(b_i\)。将\(v_i\)......