题解-USACO18DEC Sort It Out
Problem
题意概要:给定一个长为\(n\)的排列,可以选择一个集合\(S\)使这个集合内部元素排到自己在整个序列中应该在的位置(即对于集合\(S\)内的每一个元素\(i\),使其排到第\(i\)号位置,使得整个排列在排序后为上升序列。求满足这样条件的,且集合大小最小的集合中字典序第\(k\)小的集合(可能总结不到位,看链接里的吧)
\(n\leq 10^5\)
Solution
不难发现出题人费尽心思写的题面就是在强烈暗示选取一个集合等价于将这个集合内所有元素排到自己该处于的位置(即元素\(i\)应该在位置\(i\))
进一步发现集合内的元素很自觉的到了正确的位置,而集合外的元素不会更改相对位置,为了使最终整个排列单调递增,即要求集合外的元素必须满足在一开始就是单调递增的
求字典序第\(k\)小的满足题意的集合,取反一下,就是求序列中字典序第\(k\)大的最长上升子序列
(至此题目模型转化完成)
现在目标为求字典序第\(k\)大的最长上升子序列
在继续之前建议先将最长递增子序列的数量解决:
设置\(f_i\)表示以权值为\(i\)结尾的\(LIS\)的长度和数量,则权值\(x\)从\(f_1...f_{x-1}\)间转移,用树状数组维护前缀最大值和数量即可\(O(n\log n)\)解决
利用上面这题的思想,已经可以求得以每个元素开头的\(LIS\)长度和数量
这题和上面这题虽有不同,但本质类似,想想一般线段树求第 \(k\) 大的过程,正是依次确定每一层的节点,而为了确定每一层的节点,就需要用到所有节点子树和
同理,假设当前要求的序列的\(LIS\)长度为 \(t\),则求第\(k\)大\(LIS\)的一个思想就是先确定第\(1\)个数,再在确定第\(1\)个数的基础上确定下一个数……以此类推可以最终确定\(LIS\)的每一位
细化一下,就是将所有可能作为\(LIS\)的第\(i\)位的数 放进第\(i\)个vector里,将每个vector内部进行元素排序,在确定每一位时从大到小确定,若当前值后面牵扯的\(LIS\)数量小于\(k\),则将\(k\)减去这个数量然后检查下一个值,否则将这个值确定下来并开始确认下一位
(值得注意的一点,若求\(LIS\)第\(i\)层选定了位置\(R\)的元素,则接下来都不能选择\(R\)左边的元素)
Code
关于代码中的一些疑问:
- 我没有用vector,而是使用链式前向星替代
- 由于每个vector里的元素一定是按照位置递增而权值递减的,所以并不需要排序
- 很多人用线段树,而这题只需要树状数组即可
- 在求完以每个点开始的\(LIS\)后树状数组就没用了,可以节约大量时间
#include <bits/stdc++.h>
typedef long long ll;
inline void read(int&x){
char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
}
const int N=101000;
struct Edge{int v,nxt;}e[N];
int a[N],chs[N],head[N];
int n,_;ll k;
const ll lim=1e18;
struct node{
int v;ll c;
inline node(){}
friend inline void operator + (node&A,const node B){
if(A.v<B.v)A.v=B.v,A.c=B.c;
else if(A.v==B.v)A.c=std::min(lim,A.c+B.c);
}
}d[N],g[N],cl;
#define lb(x) (x&(-x))
inline node qy(int x){node p=cl;for(x;x<=n+1;x+=lb(x))p+d[x];return p;}
inline void add(int x,node y){for(;x;x-=lb(x))d[x]+y;}
inline void ae(int u,int v){e[++_].v=v,e[_].nxt=head[u],head[u]=_;}
int main(){
scanf("%d%lld",&n,&k);
for(int i=1;i<=n;++i)read(a[i]);
cl.c=1,add(n+1,cl),cl.c=0;
for(int i=n;i;--i){
g[i]=qy(a[i]);
++g[i].v;
add(a[i],g[i]);
}
for(int i=n;i;--i)ae(g[i].v,i);
for(int stp=qy(1).v,R=0;stp;--stp)
for(int i=head[stp],v;i;i=e[i].nxt){
v=e[i].v;
if(g[v].c<k)k-=g[v].c;
else {
chs[a[v]]=true;
while(R<v)g[R++]=cl;
break;
}
}
printf("%d\n",n-qy(1).v);
for(int i=1;i<=n;++i)
if(!chs[i])printf("%d\n",i);
return 0;
}
题解-USACO18DEC Sort It Out的更多相关文章
- 题解-USACO18DEC Balance Beam详细证明
(翻了翻其他的题解,觉得它们没讲清楚这个策略的正确性) Problem 洛谷5155 题意概要:给定一个长为\(n\)的序列,可以选择以\(\frac 12\)的概率进行左右移动,也可以结束并得到当前 ...
- LeetCode题解之Sort List
1.题目描述 2.问题分析 使用sort算法 3.代码 ListNode* sortList(ListNode* head) { if( head == NULL || head->next = ...
- [LeetCode 题解]: Insertion Sort List
Sort a linked list using insertion sort. 题目要求:链表的插入排序,由于没有时间复杂度的要求,可以直接循环操作. /** * Definition for si ...
- [USACO18DEC]Sort It Out(树状数组)
[Luogu5156] 题解 求字典序第 k 小的满足题意的集合,取反一下,就是求序列中字典序第 k 大的最长上升子序列 [51nod1376] 最长递增子序列的数量 置 \(f_{i}\)表示以权值 ...
- [USACO18DEC]Sort It Out P
初看本题毫无思路,只能从特殊的 \(K = 1\) 出发. 但是直接考虑构造一组字典序最小的方案还是不好构造,可以考虑先手玩一下样例.通过自己手玩的样例可以发现,貌似没有被选出来的数在原排列中都是递增 ...
- PAT甲题题解-1067. Sort with Swap(0,*) (25)-贪心算法
贪心算法 次数最少的方法,即:1.每次都将0与应该放置在0位置的数字交换即可.2.如果0处在自己位置上,那么随便与一个不处在自己位置上的数交换,重复上一步即可.拿样例举例: 0 1 2 3 4 5 ...
- 洛谷P5156 [USACO18DEC]Sort It Out
这题就是让你求字典序第k小的最短乱序子序列 转换一下,其实就是字典序第k大的最长上升子序列 就统计一下以i结尾的最长上升子序列\(f[i]\),长度为i的上升子序列的开头组成的集合\(v[i]\),转 ...
- p5156 [USACO18DEC]Sort It Out
传送门 分析 我们发现对于没有发现的点相对位置不会发生改变 于是我们可以吧问题转化为求一个lis 于是我们字典序第k小的答案就是字典序第k大的lis 代码 #include<iostream&g ...
- 题解 [USACO18DEC]Balance Beam
被概率冲昏的头脑~~~ 我们先将样例在图上画下来: 会发现,最大收益是: 看出什么了吗? 这不就是凸包吗? 跑一遍凸包就好了呀,这些点中,如果i号点是凸包上的点,那么它的ans就是自己(第二个点),不 ...
随机推荐
- vue实现筛选功能,文字选中变色
<template> <Poptip trigger="hover" title="Title" content="content& ...
- SpringBoot+Thyemleaf
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...
- Spark设计理念与基本架构
1.基本概念 Spark中的一些概念: RDD(resillient distributed dataset):弹性分布式数据集. Partition:数据分区.即一个RDD的数据可以划分为多少个分区 ...
- java实现Excel数据导出
java实现Excel数据导出: 目前,比较常用的实现Java导入.导出Excel的技术有两种Jakarta POI和Java Excel Jakarta POI 是一套用于访问微软格式文档的Java ...
- 微信小程序,错误{"errMsg":"request:fail 小程序要求的 TLS 版本必须大于等于 1.2"}
解决方法一: 开发环境,项目--->勾选不校验即可 解决办法二: 在 PowerShell中运行以下内容, 然后重启服务器 # Enables TLS R2 and Windows # Thes ...
- Scrapy基础01
一.Scarpy简介 Scrapy基于事件驱动网络框架 Twisted 编写.(Event-driven networking) 因此,Scrapy基于并发性考虑由非阻塞(即异步)的实现. 参考:武S ...
- 十四、文件和目录——文件时间和utime函数
14.1 文件时间 存在于 stat 结构体中 14.2 文件时间函数 14.2.1 介绍 utime(修改文件的存取时间和更改时间) 相关函数 utimes,stat #include <sy ...
- 【LDAP】LDAP注入漏洞与防御
0x01 前言 前两天爆了一个LDAP漏洞,据说存在了8年现在才被发现,感概一下,不知这8年来有多少站被搞了... 想着复现这个漏洞,就先复习一下LDAP注入的相关知识吧,差了很多资料,记一下笔记. ...
- 大规模数据导入和导出(sqlserver)
请期待... https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-tools#RHEL msodbcsql-13.1.6 ...
- 【刷题记录】BZOJ-USACO
接下来要滚去bzoj刷usaco的题目辣=v=在博客记录一下刷题情况,以及存一存代码咯.加油! 1.[bzoj1597][Usaco2008 Mar]土地购买 #include<cstdio&g ...