[Luogu5156]

题解

求字典序第 k 小的满足题意的集合,取反一下,就是求序列中字典序第 k 大的最长上升子序列

[51nod1376] 最长递增子序列的数量

置 \(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(树状数组)的更多相关文章

  1. HDU 2689 Sort it【树状数组】

    Sort it Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  2. nyoj322 sort 归并排序,树状数组

    Sort 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 You want to processe a sequence of n distinct integers b ...

  3. Bubble Sort HDU - 5775 树状数组

    //每个数字只会被它后面的比它小的数字影响,且会向右移动相应个数的位置 //比如:6 4 3 5 2 1 .4后面比它小的有 三个,因此它的最右边位置就是当前位置 +3,即5 //如果该数字本身在标准 ...

  4. 2016 Multi-University Training Contest 4 Bubble Sort(树状数组模板)

    Bubble Sort 题意: 给你一个1~n的排列,问冒泡排序过程中,数字i(1<=i<=n)所到达的最左位置与最右位置的差值的绝对值是多少 题解: 数字i多能到达的最左位置为min(s ...

  5. hdu_5775_Bubble Sort(树状数组)

    题目链接:hdu_5775_Bubble Sort 题意: 让你找每一个数在冒泡排序中最右边和最左边的位置的差值 题解: 还是官方题解,讲的已经很清楚了 1012 Bubble Sort 考虑一个位置 ...

  6. hdu 5775 Bubble Sort 树状数组

    Bubble Sort 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 Description P is a permutation of t ...

  7. codeforces 652D D. Nested Segments(离散化+sort+树状数组)

    题目链接: D. Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  8. HDU 5775:Bubble Sort(树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=5775 Bubble Sort Problem Description   P is a permutation ...

  9. AtCoder Regular Contest 088 E - Papple Sort(树状数组+结论)

    结论:每次把字符丢到最外面最优,用树状数组统计答案,把字符放到最外边后可以当成消失了,直接在树状数组上删掉就好. 感性理解是把字符丢到中间会增加其他字符的移动次数,但是丢到外面不会,所以是正确的. # ...

随机推荐

  1. C#连接MSSQL

    本文将介绍如何用C#连接MSSQL,C#连接SQL十分简单.我们一步一步来操作. 1.打开Microsoft SQL Server Management Studio创建一个数据库,这里我创建一个数据 ...

  2. Android实现智能提示的文本输入框AutoCompleteTextView

    今天我们要讲一个十分简单的内容,就是一个安卓控件的使用,用法很简单,但是很常用的一个.这里我用两种不同的写法来处理.当然,无论用哪一种写法,效果都是一样的. 我们先来看效果图. 要实现这种效果十分简单 ...

  3. Github中README.md换行

    两个以上的空格,然后回车.我date

  4. MySQL存储引擎 -- MyISAM(表锁定) 与 InnoDB(行锁定) 锁定机制

    前言 为了保证数据的一致完整性,任何一个数据库都存在锁定机制.锁定机制的优劣直接应想到一个数据库系统的并发处理能力和性能,所以锁定机制的实现也就成为了各种数据库的核心技术之一.本章将对MySQL中两种 ...

  5. 【摘自张宴的"实战:Nginx"】使用nginx的proxy_cache模块替代squid,缓存静态文件

    #user nobody;worker_processes 1; error_log logs/static_source.error.log;#error_log logs/error.log no ...

  6. STM32 C++编程 004 Adc (数模转换)类

    使用 C++ 语言给 STM32 编写一个 Adc 类 我使用的STM32芯片:STM32F103ZET6 我们使用的STM32库版本:V3.5.0 注意: 想学习本套 STM32 C++编程 的专栏 ...

  7. 10.model/view实例(2)

    任务:显示一个2x3的表格,将表格中的数据显示如下: 思考: 1.如何显示数据和上个例子一样. 2.但是每个单元格的数据都是有角色划分的. Qt::ItemDataRole 3.View从Model中 ...

  8. DIY的RPM包怎么签名呢 - 笔记

    参考 https://gist.github.com/fernandoaleman/1376720 如果打不开上一个连接,请参考https://www.cnblogs.com/LiuYanYGZ/p/ ...

  9. format Code

    setting中设置format code. 方便格式化代码.

  10. TimerTask

    当TimerTask实例通过schedule方法使用之后,不能通过schedule方法调用第二次,如果重复使用就会抛异常TimerTask is scheduled already. 当你重新想利用这 ...