[USACO18DEC]Sort It Out(树状数组)
求字典序第 k 小的满足题意的集合,取反一下,就是求序列中字典序第 k 大的最长上升子序列
置 \(f_{i}\)表示以权值为 i 结尾的 LIS 的长度和数量,则权值 x 从 $ f_{1} \dots f_{x-1}$ 间转移,用树状数组维护前缀最大值和数量即可$ O(nlog n)$解决
假设当前要求的序列的 LIS 长度为 t ,则求第 k 大 LIS 的一个思想就是先确定第 1 个数,再在确定第 1 个数的基础上确定下一个数……以此类推可以最终确定 LIS 的每一位
细化一下,就是将所有可能作为 LIS 的第 i 位的数 放进第 i 个vector里,将每个vector内部进行元素排序,在确定每一位时从大到小确定,若当前值后面牵扯的 LIS 数量小于 k ,则将 k 减去这个数量然后检查下一个值,否则将这个值确定下来并开始确认下一位 , 也可以用链式前向星的方法实现
(值得注意的一点,若求 LIS 第 i 层选定了位置 R 的元素,则接下来都不能选择 R 左边的元素)
代码十分巧妙,值得学习
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
}
const int MAXN=1e5+5;
const LL limit=1e18;
struct Node{
int len;LL x;
inline friend void operator += (Node &A,Node B){
if(B.len>A.len) A.len=B.len,A.x=B.x;
else if(B.len==A.len) A.x=min(A.x+B.x,limit);
}//树状数组维护最大长度和方案数
}f[MAXN];
int n;LL K;
struct BIT{
Node a[MAXN];
inline void insert(int x,Node y){
for(;x;x-=x&-x) a[x]+=y;
}
inline Node query(int x){
Node res=(Node){0,0};
for(;x<=n+1;x+=x&-x) res+=a[x];
return res;
}
}T;
struct Edge{
int v,next;
}e[MAXN];
int first[MAXN],Ecnt;
inline void Add_edge(int u,int v){
e[++Ecnt]=(Edge){v,first[u]};
first[u]=Ecnt;
}
int num[MAXN];
bool choose[MAXN];
signed main(){
n=read(),K=read();
T.insert(n+1,(Node){0,1});//按题意模拟上升序列
for(int i=1;i<=n;i++) num[i]=read();
for(int i=n;i>=1;i--){
f[i]=T.query(num[i]);//num[i]是个排列
f[i].len++;
T.insert(num[i],f[i]);
}
for(int i=n;i>=1;i--)
Add_edge(f[i].len,i);
for(int now=T.query(1).len,R=1;now;now--)
for(int i=first[now];i;i=e[i].next){//从右往左加边,从左往右遍历
int v=e[i].v;
if(K>f[v].x) K-=f[v].x;//找到第K大上升序列
else{
choose[num[v]]=true;
while(R<v) f[R++]=(Node){0,0};//选了这个数,在它左边的都不能选
break;//到剩下的下一层去再找第K大
}
}
printf("%d\n",n-T.query(1).len);
for(int i=1;i<=n;i++){
if(!choose[i]) printf("%d\n",i);//没被选中的,就是第K小的排列
}
}
[USACO18DEC]Sort It Out(树状数组)的更多相关文章
- HDU 2689 Sort it【树状数组】
Sort it Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- nyoj322 sort 归并排序,树状数组
Sort 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 You want to processe a sequence of n distinct integers b ...
- Bubble Sort HDU - 5775 树状数组
//每个数字只会被它后面的比它小的数字影响,且会向右移动相应个数的位置 //比如:6 4 3 5 2 1 .4后面比它小的有 三个,因此它的最右边位置就是当前位置 +3,即5 //如果该数字本身在标准 ...
- 2016 Multi-University Training Contest 4 Bubble Sort(树状数组模板)
Bubble Sort 题意: 给你一个1~n的排列,问冒泡排序过程中,数字i(1<=i<=n)所到达的最左位置与最右位置的差值的绝对值是多少 题解: 数字i多能到达的最左位置为min(s ...
- hdu_5775_Bubble Sort(树状数组)
题目链接:hdu_5775_Bubble Sort 题意: 让你找每一个数在冒泡排序中最右边和最左边的位置的差值 题解: 还是官方题解,讲的已经很清楚了 1012 Bubble Sort 考虑一个位置 ...
- hdu 5775 Bubble Sort 树状数组
Bubble Sort 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 Description P is a permutation of t ...
- codeforces 652D D. Nested Segments(离散化+sort+树状数组)
题目链接: D. Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
- HDU 5775:Bubble Sort(树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=5775 Bubble Sort Problem Description P is a permutation ...
- AtCoder Regular Contest 088 E - Papple Sort(树状数组+结论)
结论:每次把字符丢到最外面最优,用树状数组统计答案,把字符放到最外边后可以当成消失了,直接在树状数组上删掉就好. 感性理解是把字符丢到中间会增加其他字符的移动次数,但是丢到外面不会,所以是正确的. # ...
随机推荐
- Webrtc服务器搭建<转>
http://blog.csdn.net/zqf_office/article/details/49851209
- cookie禁用后重定向跳转时session的跟踪
- android手势(gesture)
需要实现两个接口,OnTouchListener ,OnGestureListener 在接口方法中实现各种事件 详见:http://www.cnblogs.com/JczmDeveloper/p/3 ...
- SQL查询语句 [2]
一.快捷查询 快捷查询方式是一种多字段查询的简化写法,在多个字段之间用'|'隔开表示OR,用'&'隔开表示 AND. 1.不同字段相同查询条件 在 Home/controller/UserC ...
- centos 安装 python flask 和python3安装flask
pip install Flask python3安装 pip3 install flask
- 463. Island Perimeter岛屿周长
[抄题]: You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 re ...
- JavaWeb_增强for循环
引入增强for循环的原因:在JDK5以前的版本中,遍历数组或集合中的元素,需要先获得数组的长度或集合的迭代器,比较麻烦. JDK5中定义了一种新的语法----增强for循环,以简化此类操作.增强for ...
- java全栈day03--循环高级
今日主要内容介绍1.引用类型变量的创建及使用2.流程控制语句之选择语句3.流程控制语句之循环语句4.循环高级01创建引用类型变量公式 * A: 创建引用类型变量公式 * a: 我们要学的Scanner ...
- 设置datalist指定行的背景色
前台: <div class="table-responsive" > <table class="table table-bordered table ...
- 转【C#调用DLL的几种方法,包括C#调用C\C++\C#DLL】
C#中dll调用方法 一. DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一, ...