BZOJ5484(LIS性质+树状数组)
学习的这篇题解。
结论:
1.直观感受一下会发现找到LIS,LIS里的东西相对位置是不会变的,其他的移一移总会排序成功的,所以其他的就是最小集合了,第一问的答案就是n-LIS;
2.寻找字典序第k小的集合,相当于是寻找字典序第k大的LIS,然后把这个LIS删去,就是第二问的答案集合。
前置技能:
树状数组,及树状数组求LIS。
解决方法(请先看代码):
1.树状数组bit[i]求LIS的同时再维护一下“以比i大的数字为开头、这个LIS长度下的序列的数量”。数量超过maxk的时候min一下砍掉(是一种常见手法),因为多了也没有用它只会询问maxk以内的,否则有可能爆longlong。
2.用vector存下每个长度的LIS是以哪些位置为起点,然后按长度从大到小枚举,看看第k个是哪个LIS,标记这些数字。因为之前维护了数量,所以这时就不用从1开始一个一个枚举到k了,一下砍下去一段。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <sstream>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <fstream>
#include <bitset>
#define init(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define irep(i, a, b) for (int i = a; i >= b; i--)
using namespace std; typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
const ll INF = 1e18; template <typename T> void read(T &x) {
x = ;
int s = , c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-') s = -;
for (; isdigit(c); c = getchar())
x = x * + c - ;
x *= s;
} template <typename T> void write(T x) {
if (x < ) x = -x, putchar('-');
if (x > ) write(x / );
putchar(x % + '');
} template <typename T> void writeln(T x) {
write(x);
puts("");
} const int maxn = 1e5 + ;
const ll maxk = 1e18; int n, a[maxn];
ll k;
struct Arr {
int len;
ll cnt;
Arr() {
len = , cnt = ;
}
Arr(int a, ll b) {
len = a, cnt = b;
}
}dp[maxn], bit[maxn];
vector<int> v[maxn];
bool mark[maxn]; void Modify(Arr &a, Arr b) {
if (a.len > b.len) return;
if (a.len < b.len) {
a = b;
return;
}
a.cnt = min(maxk, a.cnt + b.cnt);
} void Update(int x, Arr val) {
for (; x; x -= x&-x)
Modify(bit[x], val);
} Arr Query(int x) {
Arr ret(, );
for (; x <= n; x += x&-x)
Modify(ret, bit[x]);
return ret;
} int main() {
read(n), read(k);
rep(i, , n) read(a[i]);
//树状数组维护一个后缀最大序列(的长度和此长度下的LIS个数),规则是:1.长度最大;2.如果长度相同,累加数量
irep(i, n, ) {//比较字典序是从左往右,所以将此长度下的cnt集中在左端,故而倒序
dp[i] = Query(a[i] + );
v[++dp[i].len].push_back(i);
Update(a[i], dp[i]);
} int LIS = Query().len;
for (int i = LIS, pos = ; i; --i) {
for (int j = v[i].size() - ; ~j; --j) {
//找字典序大的,所以倒着找。vector的插入导致其中的a[p]必然升序
int p = v[i][j];
if (dp[p].cnt < k) {//以当前数字为开头的所有LIS的数量都无法满足k的需求,则这个开头被pass
k -= dp[p].cnt;
} else {//说明要找的LIS以当前这个数字为开头
mark[a[p]] = true;
while (pos < p) dp[pos++].cnt = ;
//选定这个数以后,因为是找LIS,所以它之前的数不能再选中
break;
}
}
} writeln(n - LIS);
rep(i, , n) {
if (!mark[i])
writeln(i);
}
return ;
}
BZOJ5484(LIS性质+树状数组)的更多相关文章
- nlogn求LIS(树状数组)
之前一直是用二分 但是因为比较难理解,写的时候也容易忘记怎么写. 今天比赛讲评的时候讲了一种用树状数组求LIS的方法 (1)好理解,自然也好写(但代码量比二分的大) (2)扩展性强.这个解法顺带求出以 ...
- 「BZOJ1669」D 饥饿的牛 [Usaco2006 Oct] Hungry Cows 牛客假日团队赛5 (LIS,离散化树状数组)
链接:https://ac.nowcoder.com/acm/contest/984/D 来源:牛客网 饥饿的牛 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言 ...
- UvaLive 6667 Longest Chain (分治求三元组LIS&树状数组)
题目链接: here 题意: 和hdu4742类似.差别就是一部分三元组是直接给出的.另一部分是用他给的那个函数生成的.还有就是这里的大于是严格的大于a>b必须ax>bx,ay>by ...
- Dynamic Inversions II 逆序数的性质 树状数组求逆序数
Dynamic Inversions II Time Limit: 6000/3000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Other ...
- [noip科普]关于LIS和一类可以用树状数组优化的DP
预备知识 DP(Dynamic Programming):一种以无后效性的状态转移为基础的算法,我们可以将其不严谨地先理解为递推.例如斐波那契数列的递推求法可以不严谨地认为是DP.当然DP的状态也可以 ...
- Codeforces 486E LIS of Sequence --树状数组求LIS
题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类: 1.不属于任何一个最长子序列 2.属于其中某些但不是全部最长子序列 3.属于全部最长子序列 解法: 我们先求出dp1[i] ...
- 【Codeforces】Gym 101156E Longest Increasing Subsequences LIS+树状数组
题意 给定$n$个数,求最长上升子序列的方案数 根据数据范围要求是$O(n\log n)$ 朴素的dp方程式$f_i=max(f_j+1),a_i>a_j$,所以记方案数为$v_i$,则$v_i ...
- poj1631——树状数组求LIS
题目:http://poj.org/problem?id=1631 求LIS即可,我使用了树状数组. 代码如下: #include<iostream> #include<cstdio ...
- HDU1087(树状数组求LIS)
题是水题,学习一下用树状数组求LIS. 先离散化一下,注意去重:然后就把a[i]作为下标,dp[i]作为值,max作为维护的运算插进树状数组即可. 如果是上升子序列,询问(a[i] - 1):如果是不 ...
随机推荐
- bootstrap-Table服务端分页,获取到的数据怎么再页面的表格里显示
<table class="table table-hover" id="userTable" > <thead> <tr> ...
- 6.游戏特别离不开脚本(4)-应该避免将集合框架对象传给JS
java map 传给 javascript 不是自动关联的,最好别传啊,遍历起来也麻烦(尽量避开集合框架吧),用数组或者自建一个对象.这里虽然有种方法: // build a Map Map< ...
- iOS 视图在不同View之间的切换(对于convertRect:函数的一些理解)
可以通过以下函数完成坐标体系在不同View之间的切换,如下面是完成当前View向ParentView坐标的转换(一个矩阵转换)CGRect parentRect = [currentView conv ...
- spring boot---WebFilter注解 实现自定义登录过滤器
https://my.oschina.net/wangnian/blog/647976 http://www.jianshu.com/p/05c8be17c80a
- php与html 表单的结合
PHP $_POST <!DOCTYPE html> <html> <body> <form method="post" action=& ...
- 解决VMware安装Ubuntu的过程中窗口过小无法看到【下一步】按钮的问题
只要按住ALT键向上拖动窗口
- codeforces B. Balls Game 解题报告
题目链接:http://codeforces.com/problemset/problem/430/B 题目意思:给出用不多于k种颜色对n个球的染色情况,以及手中的唯一一个球的颜色.初始时,连续的相同 ...
- PHP Framework MVC Benchmark 基准测试
身边有朋友在用yaf框架,讨论的也声音也比较多,今天没事看鸟哥的博客,看到一篇现在PHP主流的几个框架性能对比,比较有意思,给大家分享一下! Yaf是用PHP扩展的形式写的一个PHP框架,也就是以C语 ...
- CGAffineTransform属性
transform我们一般称为形变属性,其本质是通过矩阵变化改变控件的大小.位置.角度等,这里我们通过一个例子来看一下具体的操作,在下面的例子中我们也会看到UIImageView控件的常用操作. - ...
- [AHOI 2005] 航线规划
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1969 [算法] 首先离线 , 将删边操作转化为加边操作 不妨首先将这张图按边-双连通 ...