【LG2839】[国家集训队]middle
【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的更多相关文章
- [国家集训队]middle 解题报告
[国家集训队]middle 主席树的想法感觉挺妙的,但是这题数据范围这么小,直接分块草过去不就好了吗 二分是要二分的,把\(<x\)置\(-1\),\(\ge x\)的置\(1\),于是我们需要 ...
- [国家集训队]middle
[国家集训队]middle 题目 解法 开\(n\)颗线段树,将第\(i\)颗线段树中大于等于第\(i\)小的数权值赋为1,其他的则为-1,对于每个区间维护一个区间和,最大前缀和,最大后缀和. 然后二 ...
- P2839 [国家集训队]middle
P2839 [国家集训队]middle 好妙的题啊,,,, 首先二分一个答案k,把数列里>=k的数置为1,=0就是k>=中位数,<0就是k<中位数 数列的最大和很好求哇 左边的 ...
- CF484E Sign on Fence && [国家集训队]middle
CF484E Sign on Fence #include<bits/stdc++.h> #define RG register #define IL inline #define _ 1 ...
- BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)
BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...
- luogu2839 [国家集训队]middle
题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排 ...
- 解题:国家集训队 Middle
题面 求中位数的套路:二分,大于等于的设为1,小于的设为-1 于是可以从小到大排序后依次加入可持久化线段树,这样每次只会变化一个位置 那左右端点是区间怎么办? 先把中间的算上,然后维护每个区间左右两侧 ...
- [洛谷P2839][国家集训队]middle
题目大意:给你一个长度为$n$的序列$s$.$Q$个询问,问在$s$中的左端点在$[a,b]$之间,右端点在$[c,d]$之间的子段中,最大的中位数. 强制在线. 题解:区间中位数?二分答案,如果询问 ...
- Luogu 2839 [国家集训队]middle
感觉这题挺好的. 首先对于中位数最大有一个很经典的处理方法就是二分,每次二分一个数组中的下标$mid$,然后我们把$mid$代回到原来的数组中检查,如果一个数$a_{i} \geq mid$,那么就把 ...
随机推荐
- python字符串的拼接
方式一:使用"+"拼接(拼接字符串较多时会影响拼接效率) 方式二:使用","拼接(只能用于print打印,赋值操作会生成元组) 方式三:使用"%&qu ...
- Entity Framework Core今日所得:避免 IEnumerable 以及 IQueryable 陷阱
避免 IEnumerable 以及 IQueryable 陷阱: IEnumerable示用Linq会先去数据库查询所有记录,然后再条件查询. IQueryable接口派生自IEnumerable,但 ...
- JavaScript入门(一)
JavaScript入门篇—开篇 Document对象 1Document对象表示当前页面,HTML在浏览器中是以DOM形式表示为树形结构.Document是DOM树的根节点.(因此需要查找DOM树中 ...
- 门控循环单元(GRU)与 LSTM 的区别
29 November 2019 14:48 GRU is a popular variant of LSTM which replaces the forget gate and the input ...
- spark任务分配----TaskSchedulerImpl源码解析
TaskSchedulerImpl 上一篇讲到DAGScheduler根据shuffle依赖对作业的整个计算链划分成多个stage之后,就开始提交最后一个ResultStage,而由于stage之间的 ...
- 为元素添加 title 属性
---恢复内容开始--- 可以使用title属性(不要与title元素混淆)为网站上任何部分加上提示标签. ... <ul title="Table of Contents" ...
- Vue学习之过滤器和自定义指令小结(三)
过滤器: 过滤是一个数据经过了这个过滤之后出来另一样东西,可以是从中取得你想要的,或者给那个数据添加点什么装饰.过滤器就是过滤用的工具.渲染数据用的!!! 我们需要知道的是: 1.Vue中的过滤器不能 ...
- 关于web浏览器的Web SQL和IndexedDB
虽然在HTML5 WebStorage介绍了html5本地存储的Local Storage和Session Storage,这两个是以键值对存储的解决方案,存储少量数据结构很有用,但是对于大量结构化数 ...
- Java 之 Scanner 类
一.Scanner 类 Scanner 是一个可以解析基本类型和字符串的简单文本扫描器. Demo: Scanner sc = new Scanner(System.in); int i = sc.n ...
- HTML5 表单新增内容
一.H5 新增控件 1.datalist 元素 datalist 标签定义选项列表,请与 input 元素配合使用该元素.可为输入框提供一个可选的列表,可以直接选择列表项,也可以不选择列表中的项,自行 ...