【LG2839】[国家集训队]middle

题面

洛谷

题解

按照求中位数的套路,我们二分答案\(mid\),将大于等于\(mid\)的数设为\(1\),否则为\(-1\)。

若一个区间和大于等于\(0\),则答案可以更大,反之亦然。

对于这个题,我们只要维护出\([b+1,c-1]\)之间二分答案后的和,\([a,b]\)的最大右段和,\([c,d]\)的最大左段和,判断这三项加起来是否大于零即可。

我们维护这三项和的话,按照权值为前缀,建主席树就行了。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 2e4 + 5;
struct Info {
int lmax, rmax, sum;
Info () {lmax = rmax = -1, sum = 0; }
Info (int lmax, int rmax, int sum) : lmax(lmax), rmax(rmax), sum(sum) { }
} ;
Info operator + (Info l, Info r) {
Info res;
res.lmax = max(l.lmax, l.sum + r.lmax);
res.rmax = max(r.rmax, r.sum + l.rmax);
res.sum = l.sum + r.sum;
return res;
}
struct Node { int ls, rs; Info v; } t[MAX_N * 20];
int rt[MAX_N], tot = 0;
void build(int &o, int l, int r) {
o = ++tot;
t[o].v = (Info){r - l + 1, r - l + 1, r - l + 1};
if (l == r) return ;
int mid = (l + r) >> 1;
build(t[o].ls, l, mid);
build(t[o].rs, mid + 1, r);
}
void insert(int &o, int p, int l, int r, int pos) {
o = ++tot, t[o] = t[p];
if (l == r) return (void)(t[o].v = (Info){-1, -1, -1});
int mid = (l + r) >> 1;
if (pos <= mid) insert(t[o].ls, t[p].ls, l, mid, pos);
else insert(t[o].rs, t[p].rs, mid + 1, r, pos);
t[o].v = t[t[o].ls].v + t[t[o].rs].v;
}
Info query(int o, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return t[o].v;
int mid = (l + r) >> 1; Info res;
if (ql <= mid) res = res + query(t[o].ls, l, mid, ql, qr);
if (qr > mid) res = res + query(t[o].rs, mid + 1, r, ql, qr);
return res;
}
int N, id[MAX_N], a[MAX_N], q[5];
bool check(int mid) {
int val = 0;
if (q[1] + 1 <= q[2] - 1) val += query(rt[mid], 1, N, q[1] + 1, q[2] - 1).sum;
val += query(rt[mid], 1, N, q[0], q[1]).rmax;
val += query(rt[mid], 1, N, q[2], q[3]).lmax;
return val >= 0;
}
bool cmp(const int &x, const int &y) { return a[x] < a[y]; }
int main() {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
N = gi(); build(rt[1], 1, N);
for (int i = 1; i <= N; i++) a[i] = gi(), id[i] = i;
sort(&id[1], &id[N + 1], cmp);
for (int i = 2; i <= N; i++) insert(rt[i], rt[i - 1], 1, N, id[i - 1]);
for (int Q = gi(), ans = 0; Q--; ) {
for (int i = 0; i < 4; i++) q[i] = (gi() + ans) % N + 1;
sort(&q[0], &q[4]);
int l = 1, r = N;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) ans = a[id[mid]], l = mid + 1;
else r = mid - 1;
}
printf("%d\n", ans);
}
return 0;
}

【LG2839】[国家集训队]middle的更多相关文章

  1. [国家集训队]middle 解题报告

    [国家集训队]middle 主席树的想法感觉挺妙的,但是这题数据范围这么小,直接分块草过去不就好了吗 二分是要二分的,把\(<x\)置\(-1\),\(\ge x\)的置\(1\),于是我们需要 ...

  2. [国家集训队]middle

    [国家集训队]middle 题目 解法 开\(n\)颗线段树,将第\(i\)颗线段树中大于等于第\(i\)小的数权值赋为1,其他的则为-1,对于每个区间维护一个区间和,最大前缀和,最大后缀和. 然后二 ...

  3. P2839 [国家集训队]middle

    P2839 [国家集训队]middle 好妙的题啊,,,, 首先二分一个答案k,把数列里>=k的数置为1,=0就是k>=中位数,<0就是k<中位数 数列的最大和很好求哇 左边的 ...

  4. CF484E Sign on Fence && [国家集训队]middle

    CF484E Sign on Fence #include<bits/stdc++.h> #define RG register #define IL inline #define _ 1 ...

  5. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  6. luogu2839 [国家集训队]middle

    题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排 ...

  7. 解题:国家集训队 Middle

    题面 求中位数的套路:二分,大于等于的设为1,小于的设为-1 于是可以从小到大排序后依次加入可持久化线段树,这样每次只会变化一个位置 那左右端点是区间怎么办? 先把中间的算上,然后维护每个区间左右两侧 ...

  8. [洛谷P2839][国家集训队]middle

    题目大意:给你一个长度为$n$的序列$s$.$Q$个询问,问在$s$中的左端点在$[a,b]$之间,右端点在$[c,d]$之间的子段中,最大的中位数. 强制在线. 题解:区间中位数?二分答案,如果询问 ...

  9. Luogu 2839 [国家集训队]middle

    感觉这题挺好的. 首先对于中位数最大有一个很经典的处理方法就是二分,每次二分一个数组中的下标$mid$,然后我们把$mid$代回到原来的数组中检查,如果一个数$a_{i} \geq mid$,那么就把 ...

随机推荐

  1. [转] Vue原理解析——自己写个Vue

    一.Vue对比其他框架原理 Vue相对于React,Angular更加综合一点.AngularJS则使用了“脏值检测”. React则采用避免直接操作DOM的虚拟dom树.而Vue则采用的是 Obje ...

  2. asp.net 报错 SAP 报错 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)

    “/”应用程序中的服务器错误. 试图加载格式不正确的程序. (异常来自 HRESULT:0x8007000B) 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该 ...

  3. Linux下通过md5sum生成MD5文件&校验MD5

    生成md5值 随便找个文件执行:md5sum file_name  即可生成该文件对应md5值. 也可以一次生成多个文件的md5值:md5sum file_name1 file_name2 file_ ...

  4. 浏览器解析js

    网页加载js步骤 1.浏览器一边下载html网页,一边开始解析(不等下载完就解析)2.遇到<script>标签,暂停解析,网页渲染的控制权交给javascript引擎3.如果<scr ...

  5. logback配置和使用

    简介 logback是由log4j创始人设计的又一个开源日志组件.当前分成三个模块: logback-core是其它两个模块的基础模块. logback-classic是log4j的一个 改良版本.此 ...

  6. 基于react-app搭建react-router+redux项目

    前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...

  7. mmap vs read

    先放个结论: 内存映射通常比随机访问更快,尤其访问的对象是分离的和不可预测的. 内存映射会持续占用pages, 直到完成访问. 这意味当长时间重度使用一个文件很久之前, 然后你关闭了它, 然后再重新打 ...

  8. 上传文件至Github仓库

    Github的使用 创建一个本地的版本库(也就是一个文件夹) 新建文件夹,或使用Git bash命令行窗口创建 $ mkdir test $ cd test 在命令行中输入 git init把这个文件 ...

  9. Android 8.0编译过程

    Android编译系统中的Android.bp.Blueprint与Soonghttp://note.qidong.name/2017/08/android-blueprint/ 工具链关系 Andr ...

  10. 转 根据CPU核心数确定线程池并发线程数

    转自: https://www.cnblogs.com/dennyzhangdd/p/6909771.html?utm_source=itdadao&utm_medium=referral 目 ...