感觉这题挺好的。

首先对于中位数最大有一个很经典的处理方法就是二分,每次二分一个数组中的下标$mid$,然后我们把$mid$代回到原来的数组中检查,如果一个数$a_{i} \geq mid$,那么就把$s_{i}$记为$1$,否则把$s_{i}$记为$-1$,然后对$s_{i}$跑一遍前缀和,观察是否有一个区间的和不小于$0$。

读清楚题意之后发现在这题中,如果要对一个长度为偶数(记为$n$)的序列求中位数,那么答案为排好序的数组中下标为$n / 2 + 1$的元素。(下标从$1$开始),不同的中位数$s_{i}$的表示方法可能有少许不同,要具体题目具体yy。

证明应当也很简单,$+1$代表一个比当前的$mid$大的数,而$-1$表示一个比当前的$a_{mid}$小的数,那么当$a_{mid}$是中位数的条件在一个区间成立的时候,这个区间的$s_{i}$和应当恰好等于$0$。而当得到了一个区间和大于$0$的区间的时候,我们可以通过扔掉几个$1$使它变成$0$,相当于之前的条件成立。

但是这样还是太慢了。

对于本题来说,每次二分得到了一个$mid$,我们检验的时候得到的答案就一定是(区间是$a, b, c, d$)$sum(b + 1, c - 1) + lmax(c, d) + rmax(a, b)$。

其中$lmax$代表一定要选左端点的最大子段和,而$rmax$代表一定要选右端点的最大子段和。

显然可以用线段树来维护。

一个元素开一颗线段树是不可能的……

我们发现在排好序中的数组里面两个下标相差$1$的元素的值其实只有$1$个不同,这就是较小的元素在原数组中的下标,那么大多数结点的值可以继承过来。

于是可以可持久化了,变成了一个主席树。

时间复杂度$O(nlog^{2}n)$。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int N = 2e4 + ;
const int inf = << ; int n, qn, a[N]; struct Innum {
int val, id;
} b[N]; bool cmp(const Innum &x, const Innum &y) {
if(x.val != y.val) return x.val < y.val;
else return x.id < y.id;
} /*bool cmp(const Innum &x, const Innum &y) {
return x.val < y.val;
} */ inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline int max(int x, int y) {
return x > y ? x : y;
} inline void chkMax(int &x, int y) {
if(y > x) x = y;
} namespace PSegT {
struct Node {
int lc, rc, sum, lmax, rmax; inline void init() {
lc = rc = sum = ;
lmax = rmax = -inf;
} } s[N * ]; int root[N], nodeCnt = ; #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define sum(p) s[p].sum
#define lmax(p) s[p].lmax
#define rmax(p) s[p].rmax
#define mid ((l + r) >> 1) inline void up(int p) {
if(!p) return;
sum(p) = sum(lc(p)) + sum(rc(p));
// lmax(p) = rmax(p) = -inf;
lmax(p) = max(lmax(lc(p)), lmax(rc(p)) + sum(lc(p)));
rmax(p) = max(rmax(rc(p)), rmax(lc(p)) + sum(rc(p)));
} void build(int &p, int l, int r) {
p = ++nodeCnt;
if(l == r) {
sum(p) = lmax(p) = rmax(p) = ;
return;
} build(lc(p), l, mid);
build(rc(p), mid + , r);
up(p);
} void modify(int &p, int l, int r, int x, int v, int pre) {
s[p = ++nodeCnt] = s[pre];
if(l == r) {
sum(p) = lmax(p) = rmax(p) = v;
return;
} if(x <= mid) modify(lc(p), l, mid, x, v, lc(pre));
else modify(rc(p), mid + , r, x, v, rc(pre));
up(p);
} Node query(int p, int l, int r, int x, int y) {
if(x <= l && y >= r) return s[p]; Node res, ln, rn;
res.init(), ln.init(), rn.init(); if(x <= mid) ln = query(lc(p), l, mid, x, y);
if(y > mid) rn = query(rc(p), mid + , r, x, y); res.sum = ln.sum + rn.sum;
res.lmax = max(ln.lmax, ln.sum + rn.lmax);
res.rmax = max(rn.rmax, rn.sum + ln.rmax); return res;
} #undef lc
#undef rc
#undef sum
#undef lmax
#undef rmax
#undef mid } using namespace PSegT; inline bool chk(int mid, int l1, int r1, int l2, int r2) {
Node now; int res = ; if(r1 + <= l2 - ) {
now.init();
now = query(root[mid], , n, r1 + , l2 - );
res += now.sum;
} now.init();
now = query(root[mid], , n, l1, r1);
res += now.rmax; now.init();
now = query(root[mid], , n, l2, r2);
res += now.lmax; return res >= ;
} inline int solve(int l1, int r1, int l2, int r2) {
int ln = , rn = n, mid, res;
for(; ln <= rn; ) {
mid = (ln + rn) / ;
if(chk(mid, l1, r1, l2, r2)) res = mid, ln = mid + ;
else rn = mid - ;
}
return b[res].val;
} int main() {
read(n);
for(int i = ; i <= n; i++) {
read(a[i]);
b[i].val = a[i], b[i].id = i;
} s[].lmax = s[].rmax = -inf;
build(root[], , n);
sort(b + , b + + n, cmp);
for(int i = ; i <= n; i++)
modify(root[i], , n, b[i - ].id, -, root[i - ]); read(qn);
for(int ans = , q[]; qn--; ) {
for(int i = ; i < ; i++) {
read(q[i]);
q[i] = (q[i] + ans) % n + ;
}
sort(q, q + );
ans = solve(q[], q[], q[], q[]);
printf("%d\n", ans);
} return ;
}

Luogu 2839 [国家集训队]middle的更多相关文章

  1. [洛谷2839/国家集训队]middle

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之 ...

  2. Luogu P2839 [国家集训队]middle

    题目 首先我们考虑解决中位数一类问题的常用手段:二分\(mid\),将大于等于它的设为\(1\),小于它的设为\(−1\),判断区间和是否\(\ge0\). 对于询问\(a,b,c,d\),二分完\( ...

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

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

  4. [国家集训队]middle

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

  5. luogu P2757 [国家集训队]等差子序列

    题目链接 luogu P2757 [国家集训队]等差子序列 题解 线段树好题 我选择暴力 代码 // luogu-judger-enable-o2 #include<cstdio> inl ...

  6. P2839 [国家集训队]middle

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

  7. luogu P2619 [国家集训队2]Tree I

    题目链接 luogu P2619 [国家集训队2]Tree I 题解 普通思路就不说了二分增量,生成树check 说一下坑点 二分时,若黑白边权有相同,因为权值相同优先选白边,若在最有增量时出现黑白等 ...

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

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

  9. 【LG2839】[国家集训队]middle

    [LG2839][国家集训队]middle 题面 洛谷 题解 按照求中位数的套路,我们二分答案\(mid\),将大于等于\(mid\)的数设为\(1\),否则为\(-1\). 若一个区间和大于等于\( ...

随机推荐

  1. 用linux搭建ranzhi环境

    一.安装红帽6.5 1.安装时需选择桥接模式: 2.选择自定义,在设置中将镜像文件(ISO)选择进去: 3.安装时选择[桌面]安装(在/etc/inittab文件中,若id=5则为桌面模式,id=3为 ...

  2. SPFA 算法(剪辑)(学习!)

    SPFA算法 单源最短路径的算法最常用的是Dijkstra,些算法从时间复杂度来说为O(n^2),但是面对含有负权植的图来说就无能为力了,此时 Dellman-ford算法就有用了,这咱算法是采用的是 ...

  3. kreuz-frankfurt-sample-generic-2019-02-08.xodr文件解读

    第1行:xml语法所遵循的版本. L2:文件封装标记. L3:Opendrive的主要修订编号  次要修订编号   供应商. L4:记录有关地理参考坐标系的参数,投影-横轴墨卡托   a-地球椭球长半 ...

  4. jQuery横向手风琴图片滑块

    jQuery横向手风琴图片滑块是一款非常不错的jQuery特效横向手风琴图片滑块插件,可以自动播放,也可以鼠标滑过时切换.+ 欢迎喜欢的朋友下载研究 源码下载页:http://www.huiyi8.c ...

  5. Spring MVC工作原理(好用版)

    Spring MVC工作原理 参考: SpringMVC工作原理 - 平凡希 - 博客园https://www.cnblogs.com/xiaoxi/p/6164383.html SpringMVC的 ...

  6. Compilation error 未完待续

    1. code.cpp:1:21: fatal error: iostream : No such file or directory #include< iostream > ^ com ...

  7. BEC listen and translation exercise 42

    These were built for the workers towards the end of the eighteenth century, and they are still furni ...

  8. SQL的CASE表达式用法

    case 表达式从SQL-92标准开始引入,因此是不依赖于具体的数据库技术,可提高SQL代码的可移植性. case表达式注意事项: 1. 统一各个分支返回数据类型,并保证各个when字句的排他性,因为 ...

  9. Struts2 - 运行流程分析

    1. 请求发送给 StrutsPrepareAndExecuteFilter 2. StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 St ...

  10. Java 网络通信(TCP/UDP)

    1.InetAdress类 与  Socket类  >InetAdress  >Socket 2.TCP/IP协议簇  客户端: 创建 Socket:根据指定服务端的 IP 地址或端口号构 ...