01二分 [AGC006D] Median Pyramid Hard + P2824 [HEOI2016/TJOI2016] 排序
[AGC006D] Median Pyramid Hard
考虑对于一个长度为 2n + 1 的 01 序列 b 如何快速确定堆顶元素。
_ _ _ _ x
_ _ _ 0 x
_ _ 0 0 x
_ x 0 0 x
x x 0 0 x
容易得到,两个相同元素能够一直往上走,直到边界。
如果有两个相同元素出现在第 n 位,那答案显然为 b[n]。
那如果不在呢?
_ _ _ _ _ 0 0 x
_ _ _ _ 0 0 1 x
_ _ _ 0 0 1 0 x
_ _ 0 0 1 0 1 x
_ 0 0 1 0 1 0 x
0 0 1 0 1 0 1 x
得到结论,交替出现的 01 段能让两个相同元素斜向上平移。
由于离中心越近,越快能平移到中心。
因此离中心最近的两个相同元素即为答案。
最后特判没有相同元素的情况,也就是 01 交替出现,显然答案为 b[1]。
回到原题,考虑二分答案。
把原序列中 >= mid 的设为 1,< mid 的设为 0。
如果堆顶为 1 说明 ans >= mid,否则 < mid。
#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); ++ i)
#define per(i, a, b) for(int i = (a); i >= (b); -- i)
#define pb emplace_back
#define All(X) X.begin(), X.end()
using namespace std;
using ll = long long;
constexpr int N = 2e5 + 5;
int n, m, a[N], b[N];
int l, r, mid;
bool check(int v) {
rep(i, 1, m) b[i] = a[i] >= v;
rep(i, 0, n - 2) {
if(b[n + i] == b[n + i + 1]) return b[n + i];
if(b[n - i] == b[n - i - 1]) return b[n - i];
}
return b[1];
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin >> n; m = n * 2 - 1;
rep(i, 1, m) cin >> a[i];
l = 1, r = m;
while(l < r) {
if(check(mid = l + r + 1 >> 1)) l = mid;
else r = mid - 1;
}
cout << l;
return 0;
}
P2824 [HEOI2016/TJOI2016] 排序
题意:对一个长度为 n 的排列排 m 次序,问最终 p 位置是哪个数。
考虑对一个 01 序列进行一次排序需要多长时间。
令 cnt 等于 [l,r] 内 1 的个数。
对于升序操作,
- 将 [l,r - cnt] 全改为 0。
- 将 [r - cnt + 1, r] 全改为 1。
降序同理。
用线段树能做到 log n。
二分答案。
把原序列中 >= mid 的设为 1,< mid 的设为 0。
进行 m 次排序。
如果目标位置为 1 说明 ans >= mid,否则 < mid。
总复杂度 \(O(m\log^2n)\)。
#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); ++ i)
#define per(i, a, b) for(int i = (a); i >= (b); -- i)
#define pb emplace_back
#define All(X) X.begin(), X.end()
using namespace std;
using ll = long long;
constexpr int N = 1e5 + 5;
struct Node {
int op, l, r;
} q[N];
struct Seg {
int v, tag, sz;
} t[N << 2];
int n, m, pos, a[N];
void pushup(int x) {
t[x].v = t[x << 1].v + t[x << 1 | 1].v;
}
void pushdown(int x) {
if(~t[x].tag) {
int l = x << 1, r = l | 1;
t[l].v = t[l].sz * t[x].tag, t[l].tag = t[x].tag;
t[r].v = t[r].sz * t[x].tag, t[r].tag = t[x].tag;
t[x].tag = -1;
}
}
void build(int v, int x = 1, int l = 1, int r = n) {
t[x] = {0, -1, r - l + 1};
if(l == r) {
t[x].v = a[l] >= v;
return;
}
int mid = l + r >> 1;
build(v, x << 1, l, mid);
build(v, x << 1 | 1, mid + 1, r);
pushup(x);
}
int query(int L, int R, int x = 1, int l = 1, int r = n) {
if(L > R) return 0;
if(L <= l && r <= R) return t[x].v;
int mid = l + r >> 1, ret = 0;
pushdown(x);
if(mid >= L) ret += query(L, R, x << 1, l, mid);
if(mid < R) ret += query(L, R, x << 1 | 1, mid + 1, r);
return ret;
}
void modify(int L, int R, int v, int x = 1, int l = 1, int r = n) {
if(L > R) return;
if(L <= l && r <= R) return t[x].v = t[x].sz * (t[x].tag = v) , void();
int mid = l + r >> 1;
pushdown(x);
if(mid >= L) modify(L, R, v, x << 1, l, mid);
if(mid < R) modify(L, R, v, x << 1 | 1, mid + 1, r);
pushup(x);
}
bool check(int v) {
build(v);
rep(i, 1, m) {
auto [op, l, r] = q[i];
int cnt = query(l, r);
if(op) {
modify(l, l + cnt - 1, 1);
modify(l + cnt, r, 0);
}
else {
modify(r - cnt + 1, r, 1);
modify(l, r - cnt, 0);
}
}
return query(pos, pos);
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin >> n >> m;
rep(i, 1, n) cin >> a[i];
rep(i, 1, m) cin >> q[i].op >> q[i].l >> q[i].r;
cin >> pos;
int l = 1, r = n;
while(l < r) {
int mid = l + r + 1 >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout << l;
return 0;
}
01二分 [AGC006D] Median Pyramid Hard + P2824 [HEOI2016/TJOI2016] 排序的更多相关文章
- [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)
题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...
- 洛谷 P2824 [HEOI2016/TJOI2016]排序 解题报告
P2824 [HEOI2016/TJOI2016]排序 题意: 有一个长度为\(n\)的1-n的排列\(m\)次操作 \((0,l,r)\)表示序列从\(l\)到\(r\)降序 \((1,l,r)\) ...
- 洛谷$P2824\ [HEOI2016/TJOI2016]$ 排序 线段树+二分
正解:线段树+二分 解题报告: 传送门$QwQ$ 昂着题好神噢我$jio$得$QwQQQQQ$,,, 开始看到长得很像之前考试题的亚子,,,然后仔细康康发现不一样昂$kk$,就这里范围是$[1,n]$ ...
- P2824 [HEOI2016/TJOI2016]排序
题面 这是一道非常巧妙的线段树的题 我们会发现维护\(1 \sim n\)的序列非常困难,但如果我们维护\(01\)序列的的顺序,就非常容易了 但是我们怎么能把这道题变成维护\(01\)序列的顺序呢? ...
- [洛谷P2824][HEOI2016/TJOI2016]排序
题目大意:一个全排列,两种操作: 1. $0\;l\;r:$把$[l,r]$升序排序2. $1\;l\;r:$把$[l,r]$降序排序 最后询问第$k$位是什么 题解:二分答案,把比这个数大的赋成$1 ...
- 洛谷P2824 [HEOI2016/TJOI2016]排序(线段树)
传送门 这题的思路好清奇 因为只有一次查询,我们考虑二分这个值为多少 将原序列转化为一个$01$序列,如果原序列上的值大于$mid$则为$1$否则为$0$ 那么排序就可以用线段树优化,设该区间内$1$ ...
- luogu P2824 [HEOI2016/TJOI2016]排序
题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行 ...
- 「Luogu P2824 [HEOI2016/TJOI2016]排序」
一道十分神奇的线段树题,做法十分的有趣. 前置芝士 线段树:一个十分基础的数据结构,在这道题中起了至关重要的作用. 一种基于01串的神奇的二分思想:在模拟赛中出现了这道题,可以先去做一下,这样可能有助 ...
- Luogu P2824 [HEOI2016/TJOI2016]排序 线段树+脑子
只会两个$log$的$qwq$ 我们二分答案:设答案为$ans$,则我们把$a[i]<=ans$全部设成$0$,把$a[i]>ans$全部设成$1$,扔到线段树里,这样区间排序(升序)就是 ...
- 洛谷 P2824 [HEOI2016/TJOI2016]排序 (线段树合并)
(另外:题解中有一种思路很高妙而且看上去可以适用一些其他情况的离线方法) 线段树合并&复杂度的简单说明:https://blog.csdn.net/zawedx/article/details ...
随机推荐
- 这里有你不得不了解的Java 11版本特性说明
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- List和ObservableCollection的转换
1.我们后台查询全部List数据的时候,前台需要ObservableCollection展示 这个时候List需要转换成ObservableCollection public static Obser ...
- #轮廓线dp#洛谷 1879 [USACO06NOV]Corn Fields G
题目 分析 考虑状压dp在\(n\leq 21\)的情况下会TLE, 设\(dp[n][m][S]\)表示当前正在处理\((n,m)\)这个格子 并且轮廓线状态为\(S\)的方案数, 考虑可行状态最多 ...
- #并查集#JZOJ 4223 旅游
题目 多次询问有多少个无序点对\((x,y)\), 满足至少有一条最大边权\(\leq d\)的路径 分析 离线询问,用并查集加边,每次产生的贡献为\(2*siz[x]*siz[y]\) 代码 #in ...
- .NET MAUI开源免费的UI工具包 - Uranium
前言 一直有小伙伴在微信公众号后台留言让我分享一下.NET MAUI相关的UI框架,今天大姚分享一个.NET MAUI开源.免费的UI工具包:Uranium. Uranium介绍 Uranium是一个 ...
- HarmonyOS语言基础类库开发指南上线啦!
语言基础类库提供哪些功能?多线程并发如何实现?TaskPool(任务池)和Worker在实现和使用场景上有何不同? 针对开发者关注的并发等语言基础类库的相关能力,我们在新推出的语言基础类库开发指南 ...
- InnoDB常用锁总结(行锁、间隙锁、临键锁、表锁)
相关文章 数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩 ...
- vue使用 elementUI中el-upload的遇到的问题总结
使用场景,使用el-upload上传文件,选择文件后不立即上传到服务器上,点击提交按钮时与其他form表单数据一起提交,类似的需求,相信有很多小伙伴遇到,可能也会遇到跟我一起的问题,在这里记录一下 & ...
- 力扣436(java&python)-寻找右区间(中等)
题目: 给你一个区间数组 intervals ,其中 intervals[i] = [starti, endi] ,且每个 starti 都 不同 . 区间 i 的 右侧区间 可以记作区间 j ,并满 ...
- 「开源人说」|AI普惠,阿里灵杰开源历程与思考
简介: 施兴 阿里巴巴资深技术专家 阿里巴巴开源项目EasyRec负责人 以下为开发者社区「开源人说」第四期--大数据&AI专场的主题分享,点击链接了解更多精彩详情 https://devel ...