「国家集训队」middle

传送门

按照中位数题的套路,二分答案 \(mid\),序列中 \(\ge mid\) 记为 \(1\),\(< mid\) 的记为 \(-1\)

然后只要存在一个区间 \([l, r](l \in [a, b], r \in [c, d])\) 的和 \(\ge 0\) 则答案可以更大,否则就更小。

所以说我们就要算出区间 \([b + 1, c - 1]\) 的和,加上 \([a, b]\) 的最大后缀,还有 \([c, d]\) 最大前缀,加起来就是我们用来 \(check\) 的值。

这些过程可以用线段树来搞,具体维护细节就和维护区间最大子段和差不多。

但是我们面临另一个问题:\(mid\) 会变,也就是我们的序列是会变的,我们不可能对于每一个 \(mid\) 都建一棵线段树。

那能不能用主席树优化空间呢?

我们发现,\(mid\) 扩大 \(1\) ,只会有一个数的值从 \(1\) 变成 \(-1\) ,也就是说我们只需要修改一条链上的信息,这显然可以用主席树来搞,空间问题也就解决了。

参考代码:

#include <algorithm>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while ('0' > c || c > '9') f |= c == '-', c = getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
s = f ? -s : s;
} typedef long long LL;
const int _ = 20005; int n, m, q[5], a[_], id[_], tot, rt[_];
struct node { int lc, rc, sum, L, R; } t[_ << 5]; inline void pushup(int p) {
t[p].sum = t[t[p].lc].sum + t[t[p].rc].sum;
t[p].L = max(t[t[p].lc].L, t[t[p].lc].sum + t[t[p].rc].L);
t[p].R = max(t[t[p].rc].R, t[t[p].rc].sum + t[t[p].lc].R);
} inline void build(int& p, int l = 1, int r = n) {
p = ++tot;
if (l == r) { t[p].sum = t[p].L = t[p].R = 1; return ; }
int mid = (l + r) >> 1;
build(t[p].lc, l, mid), build(t[p].rc, mid + 1, r), pushup(p);
} inline void update(int& p, int q, int x, int l = 1, int r = n) {
t[p = ++tot] = t[q];
if (l == r) { t[p].sum = t[p].L = t[p].R = -1; return ; }
int mid = (l + r) >> 1;
if (x <= mid) update(t[p].lc, t[q].lc, x, l, mid);
else update(t[p].rc, t[q].rc, x, mid + 1, r);
pushup(p);
} inline node query(int ql, int qr, int p, int l = 1, int r = n) {
if (ql <= l && r <= qr) return t[p];
int mid = (l + r) >> 1;
if (qr <= mid) return query(ql, qr, t[p].lc, l, mid);
if (ql > mid) return query(ql, qr, t[p].rc, mid + 1, r);
node ls = query(ql, mid, t[p].lc, l, mid), rs = query(mid + 1, qr, t[p].rc, mid + 1, r);
return (node) { 0, 0, ls.sum + rs.sum, max(ls.L, ls.sum + rs.L), max(rs.R, rs.sum + ls.R) };
} inline bool check(int mid) {
int res = 0;
if (q[1] + 1 <= q[2] - 1) res += query(q[1] + 1, q[2] - 1, rt[mid]).sum;
res += query(q[0], q[1], rt[mid]).R;
res += query(q[2], q[3], rt[mid]).L;
return res >= 0;
} inline bool cmp(int i, int j) { return a[i] < a[j]; } int main() {
#ifndef ONLINE_JUDGE
file("cpp");
#endif
read(n);
for (rg int i = 1; i <= n; ++i) read(a[i]), id[i] = i;
sort(id + 1, id + n + 1, cmp);
build(rt[1]);
for (rg int i = 2; i <= n; ++i) update(rt[i], rt[i - 1], id[i - 1]);
read(m);
for (rg int ans = 0; m--; ) {
for (rg int i = 0; i < 4; ++i) read(q[i]), q[i] = (q[i] + ans) % n + 1;
sort(q, 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;
}

「国家集训队」middle的更多相关文章

  1. 「国家集训队」小Z的袜子

    「国家集训队」小Z的袜子 传送门 莫队板子题. 注意计算答案的时候,由于分子分母都要除以2,所以可以直接约掉,这样在开桶算的时候也方便一些. 参考代码: #include <algorithm& ...

  2. P4827「国家集训队」 Crash 的文明世界

    「国家集训队」 Crash 的文明世界 提供一种不需要脑子的方法. 其实是看洛谷讨论版看出来的( (但是全网也就这一篇这个方法的题解了) 首先这是一个关于树上路径的问题,我们可以无脑上点分治. 考虑当 ...

  3. Solution -「国家集训队」「洛谷 P2839」Middle

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\),\(q\) 组询问,给定 \(a<b<c<d\),求 \(l\le[a,b] ...

  4. 「洛谷1903」「BZOJ2120」「国家集训队」数颜色【带修莫队,树套树】

    题目链接 [BZOJ传送门] [洛谷传送门] 题目大意 单点修改,区间查询有多少种数字. 解法1--树套树 可以直接暴力树套树,我比较懒,不想写. 稍微口胡一下,可以直接来一个树状数组套主席树,也就是 ...

  5. 「国家集训队」Crash的数字表格

    题目描述 求(对 \(20101009\) 取模,\(n,m\le10^7\) ) \[\sum_{i=1}^n\sum_{j=1}^m\operatorname{lcm}(i,j)\] 大体思路 推 ...

  6. Solution -「国家集训队」「洛谷 P2619」Tree I

    \(\mathcal{Description}\)   Link.   给一个 \(n\) 个点 \(m\) 条边的带权无向图,边有权值和黑白颜色,求恰选出 \(K\) 条白边构成的最小生成树.    ...

  7. Solution -「国家集训队」「洛谷 P4451」整数的 lqp 拆分

    \(\mathcal{Description}\)   Link.   求 \[\sum_{m>0\\a_{1..m}>0\\a_1+\cdots+a_m=n}\prod_{i=1}^mf ...

  8. [国家集训队2012]middle

    http://cogs.pro:8080/cogs/problem/problem.php?pid=1763 二分答案x 把区间内>=x的数设为1,<x的数设为-1 左端点在[a,b]之间 ...

  9. [国家集训队2012]middle(陈立杰)

    我是萌萌的传送门 我是另一个萌萌的传送门 脑残错误毁一下午…… 其实题解早就烂大街了,然而很久之前我只知道是二分答案+主席树却想不出来这俩玩意儿怎么一块儿用的……今天又翻了几篇题解才恍然大悟,是把权值 ...

随机推荐

  1. 爬虫(十一):selenium爬虫

    1. selenium基础 selenium部分可以去看我写的selenium基础部分,由于链接太多了这里就不发出来了. 代理ip: 有时候频繁爬取一些网页.服务器发现你是爬虫后会封掉你的ip地址.这 ...

  2. vue中子组件调用父组件里面的数据和方法 父组件调用子组件的数据和方法

    1.子组件直接调用父组件的数据和方法 在父组件father,vue <template> <div> <!-- 父组件里面的数据 --> <p>父组件里 ...

  3. React的React.createElement源码解析(一)

    一.什么是jsx  jsx是语法糖  它是js和html的组合使用  二.为什么用jsx语法 高效定义模版,编译后使用 不会带来性能问题 三.jsx语法转化为js语法  jsx语法通过babel转化为 ...

  4. 【PAT甲级】1110 Complete Binary Tree (25分)

    题意: 输入一个正整数N(<=20),代表结点个数(0~N-1),接着输入N行每行包括每个结点的左右子结点,'-'表示无该子结点,输出是否是一颗完全二叉树,是的话输出最后一个子结点否则输出根节点 ...

  5. 6_12 油田(UVa572)<图的连通块DFS>

    有一家石油公司负责探勘某块地底下的石油含量,这块地是矩行的,并且为了探勘的方便被切割为许多小块.然后使用仪器对每个小块去探勘.含有石油的小块称为一个pocket.假如两个pocket相连,则这两个po ...

  6. 安装nodejs时提示Leaving directory

    在按照标准的编译命令./configure =>make =>make install 在make的时候发生错误: ../deps/v8/src/base/platform/mutex.h ...

  7. CentOS7.6配置ip

    查看CentOS版本信息 [root@localhost ~]# cat /etc/redhat-release CentOS Linux release (Core) 配置ip [root@loca ...

  8. vscode解决java无法输入(scanner)问题

    vscode解决java无法输入问题 需要先安装java环境,->windows安装java 新建Test.java 输入代码 import java.util.Scanner; public ...

  9. eclipse 自定义代码块设置(代码模板)

    eclipse设置自定义代码模板 window -> show View -> other -> Templates 原来main模板 修改模板 再次插入

  10. Python中的bool类型

    Python 布尔类型 bool python 中布尔值使用常量True 和 False来表示:注意大小写 比较运算符< > == 等返回的类型就是bool类型:布尔类型通常在 if 和 ...