LG P2839 [国家集训队]middle
\(\text{Solution}\)
不考虑起点区间和终点区间的限制,求区间中位数
可以二分中位数,大于等于中位数的位置赋为 \(1\),小于的位置赋 \(-1\)
当区间和大于等于 \(0\) 时此数才可能为中位数
因为有多个询问,但中位数数值只可能有 \(n\) 个
所以预处理时枚举当前中位数,处理出序列此时区间和的情况,线段树即可
但一棵线段树空间是 \(O(n log n)\) 的,\(n\) 棵不可行
注意到中位数 \(m\) 到 \(m+1\) 时只有值为 \(m\) 的位置从 \(1\) 变到了 \(-1\),其他都一样
启示我们可以用主席树维护,于是这个问题就解决了
回到本题,仍旧预处理并且二分答案
起点区间和终点区间夹的区间是必选的,取出区间和即可
起点和终点待定,确定某个起点后,此起点到起点区间右端点的数都要选,终点同理,即取后缀和前缀
那么在二分中位数的情况下,前缀和后缀越大越好
维护区间和时顺便维护区间最大前后缀即可
\(\text{Code}\)
#include <cstdio>
#include <algorithm>
#define re register
using namespace std;
const int N = 20005, INF = N * 10;
int n, m, q[4], rt[N], size;
struct nod{int v, id;}a[N];
inline bool cmp(nod a, nod b){return a.v < b.v;}
struct node{int sum, lx, rx;};
struct tree{int ls, rs; node t;}seg[N * 61];
inline node operator + (const node &a, const node &b)
{
return node{a.sum + b.sum, max(a.lx, a.sum + b.lx), max(b.rx, b.sum + a.rx)};
}
void update(int &p, int pre, int l, int r, int x, int v)
{
p = ++size, seg[p] = seg[pre];
if (l == r)
{
seg[p].t.sum += v, seg[p].t.lx += v, seg[p].t.rx += v;
return;
}
int mid = l + r >> 1;
if (x <= mid) update(seg[p].ls, seg[pre].ls, l, mid, x, v);
else update(seg[p].rs, seg[pre].rs, mid + 1, r, x, v);
seg[p].t = seg[seg[p].ls].t + seg[seg[p].rs].t;
}
node query(int p, int l, int r, int tl, int tr)
{
if (tl > r || tr < l) return node{0, -INF, -INF};
if (tl <= l && r <= tr) return seg[p].t;
int mid = l + r >> 1; node res = {0, -INF, -INF};
if (tl <= mid) res = query(seg[p].ls, l, mid, tl, tr);
if (tr > mid) res = res + query(seg[p].rs, mid + 1, r, tl, tr);
return res;
}
inline int check(int mid)
{
int res = 0;
if (q[1] + 2 <= q[2]) res = query(rt[mid], 1, n, q[1] + 1, q[2] - 1).sum;
res += query(rt[mid], 1, n, q[0], q[1]).rx + query(rt[mid], 1, n, q[2], q[3]).lx;
return res >= 0;
}
int main()
{
freopen("LG2839.in", "r", stdin), freopen("LG2839.out", "w", stdout);
scanf("%d", &n);
for(re int i = 1; i <= n; i++) scanf("%d", &a[i].v), a[i].id = i;
sort(a + 1, a + n + 1, cmp);
for(re int i = 1; i <= n; i++) update(rt[1], rt[1], 1, n, i, 1);
for(re int i = 2; i <= n; i++) update(rt[i], rt[i - 1], 1, n, a[i - 1].id, -2);
scanf("%d", &m);
for(int l, r, mid, ans, lst = 0; m; --m)
{
for(int i = 0; i < 4; i++) scanf("%d", &q[i]), q[i] = (q[i] + lst) % n + 1;
sort(q, q + 4), l = 1, r = n, ans = 0;
while (l <= r)
{
mid = l + r >> 1;
if (check(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
printf("%d\n", lst = a[ans].v);
}
}
LG P2839 [国家集训队]middle的更多相关文章
- P2839 [国家集训队]middle
P2839 [国家集训队]middle 好妙的题啊,,,, 首先二分一个答案k,把数列里>=k的数置为1,=0就是k>=中位数,<0就是k<中位数 数列的最大和很好求哇 左边的 ...
- [洛谷P2839][国家集训队]middle
题目大意:给你一个长度为$n$的序列$s$.$Q$个询问,问在$s$中的左端点在$[a,b]$之间,右端点在$[c,d]$之间的子段中,最大的中位数. 强制在线. 题解:区间中位数?二分答案,如果询问 ...
- 洛谷P2839 [国家集训队]middle 主席树_二分
Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...
- Luogu P2839 [国家集训队]middle
题目 首先我们考虑解决中位数一类问题的常用手段:二分\(mid\),将大于等于它的设为\(1\),小于它的设为\(−1\),判断区间和是否\(\ge0\). 对于询问\(a,b,c,d\),二分完\( ...
- [国家集训队]middle 解题报告
[国家集训队]middle 主席树的想法感觉挺妙的,但是这题数据范围这么小,直接分块草过去不就好了吗 二分是要二分的,把\(<x\)置\(-1\),\(\ge x\)的置\(1\),于是我们需要 ...
- [国家集训队]middle
[国家集训队]middle 题目 解法 开\(n\)颗线段树,将第\(i\)颗线段树中大于等于第\(i\)小的数权值赋为1,其他的则为-1,对于每个区间维护一个区间和,最大前缀和,最大后缀和. 然后二 ...
- CF484E Sign on Fence && [国家集训队]middle
CF484E Sign on Fence #include<bits/stdc++.h> #define RG register #define IL inline #define _ 1 ...
- 【LG2839】[国家集训队]middle
[LG2839][国家集训队]middle 题面 洛谷 题解 按照求中位数的套路,我们二分答案\(mid\),将大于等于\(mid\)的数设为\(1\),否则为\(-1\). 若一个区间和大于等于\( ...
- BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)
BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...
- luogu2839 [国家集训队]middle
题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排 ...
随机推荐
- 6 STL-vector
重新系统学习c++语言,并将学习过程中的知识在这里抄录.总结.沉淀.同时希望对刷到的朋友有所帮助,一起加油哦! 生命就像一朵花,要拼尽全力绽放!死磕自个儿,身心愉悦! 写在前面,本篇章主要介绍S ...
- VMware宿主机访问虚拟机的Web服务
VMware宿主机访问虚拟机的Web服务,主要就是宿主机可以通过IP能够访问到虚拟机. 可以尝试使用以下步骤. 1.关闭虚拟机,把网络连接方式修改成桥接方式. 2.打开虚拟机后,把虚拟机的防火墙关闭. ...
- 数电第五周周结_by_yc
数电第五周周结_by_yc 基本要点: 组合逻辑电路的行为特点.经典组合逻辑电路的设计.PPA优化 组合逻辑电路设计要点: ①敏感变量列表应包含所有会影响输出的控制量: ②条件语句的完全描述, ...
- 【Spark】Day04-Spark Streaming:与离线批量比较、架构特点、入门案例、创建(队列、数据源)、转换(有状态、无状态)、输出方式、进阶(累加、转换为DF、缓存持久化)、实战(窗口统计)
一.概述 1.离线和实时计算 离线:数据量大,数据不会变化,MapReduce 实时:数据量小,计算过程要短 2.批量和流式处理 批量:冷数据,数据量大,速度慢 流:在线.实时产生的数据(快速持续到达 ...
- k8s篇-k8s集群架构及组件详解【史上最详细】
O kubernetes简介 k8s是什么 k8s是一个可移植的.可扩展的开源平台,用于管理容器化的工作负载和服务,可以促进声明式配置和自动化. k8s能做什么 1)服务发现和负载均衡 Kuberne ...
- jjava基础语法
java基础语法1 注释 注意: SDK要选择JDK1.8,且下面的语言要选择8,配置完这个环境后,JAVA才能正常运行. 单行注释 //+text 快捷键:ctrl+/ 多行注释 /*+text+ ...
- 网络工具netstat与ss
建议使用ss命令,2001年的时候netstat 1.42版本之后就没更新了,之后取代的工具是ss.netstat命令在很多场景下比较慢.ss可以显示跟netstat类似的信息,但是速度却比netst ...
- Linux基础第五章 进程控制
5.2 fork fork函数实现进程复制,类似于动物界的单性繁殖,fork函数直接创建一个子进程.这是Linux创建进程最常用的方法.在这一小节中,子进程概念指fork产生的进程,父进程指主动调用f ...
- CTFshow——funnyrsa3
题目如下: 题目分析: 发现常规rsa不存在的dp.查找资料知道 dp ≡ d mod (p - 1).意识到dp是解题关键,可能dp和n存在某种关系可以解出p或者去,跟之前有一题有点类似,求p和q之 ...
- Potree 001 Potree介绍
1.Potree是什么 Potree是一种基于WebGL的点云数据可视化解决方案,包含点云数据转化,以及进行可视化的源码.该解决方案的主要优势在于对点云数据进行了多尺度的管理,在数据传输和可视化上都做 ...