luogu2828 [HEOI2016/TJOI2016]排序
题目大意
给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:(0,l,r)表示将区间[l,r]的数字升序排序;(1,l,r)表示将区间[l,r]的数字降序排序。最后询问第q位置上的数字。n<=30000。
题解
关键词:反演。
我们假设最后q位置上的值为val。此时我们对整个序列进行排序...我们发现除了val外,其它点之间的顺序并不重要,只有其他点与val的相对大小才有意义。所以我们将原序列中位置上的值小于val的的值设为0,大于等于的设为1,整个序列上每个点的值表示的就是序列上的原值与val的大小关系。这样对01值排序用覆盖式的线段树来进行排序过程最方便了(具体看代码中的Sort)。
此时q位置上的值如果是0,则说明当前的val比答案大;若此时q位置上的值是1,则说明当前的val小于或等于答案。也就是说,val越大,最后q位上的值越有可能是0,val越小,q位上的值越有可能是1。因此我们可以用UpperBound二分得出答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std; const int MAX_N = 30010, MAX_NODE = MAX_N * 4, MAX_OP = 30010;
int OrgData[MAX_N];
int N, TotOp, P; struct RangeTree
{
private: struct Node
{
int Sum, Cover;
}_nodes[MAX_NODE];
int N; void PushDown(int cur, int l, int r)
{
if (_nodes[cur].Cover >= 0)
{
_nodes[cur * 2].Cover = _nodes[cur].Cover;
_nodes[cur * 2 + 1].Cover = _nodes[cur].Cover; int mid = (l + r) / 2;
_nodes[cur * 2].Sum = _nodes[cur].Cover * (mid - l + 1);
_nodes[cur * 2 + 1].Sum = _nodes[cur].Cover * (r - mid); _nodes[cur].Cover = -1;
}
} void PullUp(int cur)
{
_nodes[cur].Sum = _nodes[cur * 2].Sum + _nodes[cur * 2 + 1].Sum;
} void Update(int cur, int al, int ar, int sl, int sr, int cover)
{
assert(al <= sr && ar >= sl && sl <= sr);
if (al <= sl && sr <= ar)
{
_nodes[cur].Cover = cover;
_nodes[cur].Sum = cover * (sr - sl + 1);
return;
}
PushDown(cur, sl, sr);
int mid = (sl + sr) / 2;
if (al <= mid)
Update(cur * 2, al, ar, sl, mid, cover);
if (ar > mid)
Update(cur * 2 + 1, al, ar, mid + 1, sr, cover);
PullUp(cur);
} int Query(int cur, int al, int ar, int sl, int sr)
{
assert(al <= sr && ar >= sl && sl <= sr);
if (al <= sl && sr <= ar)
return _nodes[cur].Sum;
PushDown(cur, sl, sr);
int mid = (sl + sr) / 2, ans = 0;
if (al <= mid)
ans += Query(cur * 2, al, ar, sl, mid);
if (ar > mid)
ans += Query(cur * 2 + 1, al, ar, mid + 1, sr);
PullUp(cur);
return ans;
} void InitBuild(int cur, int sl, int sr, int *a)
{
if (sl == sr)
{
_nodes[cur].Sum = a[sl];
_nodes[cur].Cover = -1;
return;
}
int mid = (sl + sr) / 2;
InitBuild(cur * 2, sl, mid, a);
InitBuild(cur * 2 + 1, mid + 1, sr, a);
_nodes[cur].Cover = -1;
PullUp(cur);
} public: void Init(int n, int *a)
{
N = n;
InitBuild(1, 1, N, a);
} void Update(int l, int r, int cover)
{
if (l > r)
return;
Update(1, l, r, 1, N, cover);
} int Query(int l, int r)
{
return Query(1, l, r, 1, N);
}
}g; struct Oper//operation
{
int L, R;
bool IsUp; Oper(){}
Oper(int l, int r, int isUp):L(l),R(r),IsUp(isUp){}
}_ops[MAX_OP]; void Sort(Oper op)
{
int sum1 = g.Query(op.L, op.R);
if (op.IsUp)
{
g.Update(op.R - sum1 + 1, op.R, 1);
g.Update(op.L, op.R - sum1, 0);
}
else
{
g.Update(op.L, op.L + sum1 - 1, 1);
g.Update(op.L + sum1, op.R, 0);
}
} bool AnsNotLesser(int val)
{
static int a[MAX_N];
for (int i = 1; i <= N; i++)
a[i] = (OrgData[i] >= val);
g.Init(N, a); for (int i = 1; i <= TotOp; i++)
Sort(_ops[i]);
return g.Query(P, P) == 1;
} int UpperBound(int l, int r, bool(*InRange)(int))
{
while (l < r)
{
int mid = (l + r + 1) / 2;
if (InRange(mid))
l = mid;
else
r = mid - 1;
}
return l;
} int main()
{
scanf("%d%d", &N, &TotOp);
for (int i = 1; i <= N; i++)
scanf("%d", OrgData + i);
for (int i = 1; i <= TotOp; i++)
{
int l, r, isDown;
scanf("%d%d%d", &isDown, &l, &r);
_ops[i] = Oper(l, r, !isDown);
}
scanf("%d", &P);
printf("%d\n", UpperBound(1, N, AnsNotLesser));
return 0;
}
luogu2828 [HEOI2016/TJOI2016]排序的更多相关文章
- 洛谷 P2824 [HEOI2016/TJOI2016]排序 解题报告
P2824 [HEOI2016/TJOI2016]排序 题意: 有一个长度为\(n\)的1-n的排列\(m\)次操作 \((0,l,r)\)表示序列从\(l\)到\(r\)降序 \((1,l,r)\) ...
- [HEOI2016/TJOI2016]排序 线段树+二分
[HEOI2016/TJOI2016]排序 内存限制:256 MiB 时间限制:6000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而 ...
- [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)
题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...
- 2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串)
2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串) https://www.luogu.com.cn/problem/P2824 题意: 在 20 ...
- [HEOI2016&TJOI2016] 排序(线段树)
4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2703 Solved: 1386[S ...
- [HEOI2016/TJOI2016]排序
嘟嘟嘟 首先这题的暴力是十分好写的,而且据说能得不少分. 正解写起来不难,就是不太好想. 根据做题经验,我想到了给这个序列转化成01序列,但是接下来我就不会了.还是看了题解. 因为查询只有一个数,所以 ...
- 【线段树合并】【P2824】 [HEOI2016/TJOI2016]排序
Description 给定一个长度为 \(n\) 的排列,有 \(m\) 次操作,每次选取一段局部进行升序或降序排序,问你一波操作后某个位置上的数字是几 Hint \(1~\leq~n,~m~\le ...
- 【[HEOI2016/TJOI2016]排序】
巧妙思路题 有一个重要的思想就是把大于某一个数的数都变成\(1\),小于这个数的都变成\(0\),这个只有\(0\)和\(1\)的序列就很好处理了 由于我们只需要在最后求出一个位置上是什么数就可以了, ...
- BZOJ4552:[HEOI2016/TJOI2016]排序——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4552 https://www.luogu.org/problemnew/show/P2824 在2 ...
随机推荐
- [Android]异常4-javax.mail.AuthenticationFailedException
javax.mail.AuthenticationFailedException 背景:JavaMail发送电子邮件 异常原因: 可能一>发件人帐号.密码有误 可能二>需要使用SSL安全认 ...
- RTL Compiler之synthesis flow
1 generic RTL Compiler work flow 2 invoking RTL compiler RTL Compiler is invoked from the operating ...
- java设计模式02观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 这里主要讲一下学习内置观察者的记录,在JA ...
- CSS3设计炫目字体
阴影 .text-shadow{ text-shadow:#FF0000 0 0 10px; color:white; font-size:60px } 描边 <style> .text- ...
- 【sqli-labs】 less46 GET -Error based -Numeric -Order By Clause(GET型基于错误的数字型Order By从句注入)
http://192.168.136.128/sqli-labs-master/Less-46/?sort=1 sort=4时出现报错 说明参数是添加在order by 之后 错误信息没有屏蔽,直接使 ...
- tidyverse生态链
一套完整的数据分析流程 , 如下图所示 从图中可以看到,整个流程包括读取数据,整洁数据,数据探索和交流部分.经过前两部分, 我们可以得到一个整理好的数据,它的每一行都是一个样本 , 每一列是一个变量. ...
- Python 之re正则表达式
- 简述prototype, _proto_, constructor三者的关系
1.prototype 感概:每个函数都有一个prototype这个属性,而这个属性指向一个对象,这个对象称为原型对象 作用: a.节约内存 b.扩展属性和方法 c.实现类与类的之间的继承 2._pr ...
- yum仓库配置ftpx协议
[root@localhost ~]# iptables -F[root@localhost ~]# systemctl stop firewalld[root@localhost ~]# syste ...
- Luogu P2298 Mzc和男家丁的游戏
Mzc和男家丁的游戏 题目背景 mzc与djn的第二弹. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过上一弹的都知道).他把她们召集在了一起,他们决定玩捉迷藏.现在mzc要来寻找他的男家 ...