题目链接:洛谷

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

这里的中位数定义为,对于一个长度为$n$的序列排序之后为$a_0,a_1,\ldots,a_{n-1}$,则$a_{\lfloor\frac{n}{2}\rfloor}$为这个序列的中位数。

数据范围:$1\leq n\leq 20000$,$1\leq q\leq 25000$,$1\leq a\leq b\leq c\leq d\leq n$


这道题才是真正的主席树!

首先我们考虑离散化,然后二分答案,判断这些区间的中位数是否有可能$\geq mid$,那怎么判断呢?

我们发现,如果把这个序列的所有$\geq mid$的数改为1,$<mid$的数改为$-1$,则上述条件等价于这个新的数列之和非负。(这是一个非常神仙的套路)

所以我们对于所有的数$a_i$,预处理出这个1/-1的序列,但是这样空间会爆炸。

我们发现这些序列中,$a_{i-1}$和$a_i$的序列之间仅有一位不同。

于是主席树闪亮登场。

然后判断一下左端点在$[a,b]$,右端点在$[c,d]$的最大子段和,判断一下是否$\geq 0$。

 #include<cstdio>
#include<algorithm>
#define Rint register int
using namespace std;
const int N = ;
int n, Q, q[], lans, a[N], id[N], root[N], ls[N << ], rs[N << ], cnt;
struct Node {
int sum, lmax, rmax;
inline Node(int s = , int l = , int r = ): sum(s), lmax(l), rmax(r){}
inline Node operator + (const Node &o) const {
return Node(sum + o.sum, max(lmax, sum + o.lmax), max(o.rmax, o.sum + rmax));
}
} seg[N << ];
inline void pushup(int x){
seg[x] = seg[ls[x]] + seg[rs[x]];
}
inline void build(int &x, int L, int R){
x = ++ cnt;
if(L == R){
seg[x] = Node(, , );
return;
}
int mid = L + R >> ;
build(ls[x], L, mid);
build(rs[x], mid + , R);
pushup(x);
}
inline void change(int &nx, int ox, int L, int R, int pos){
nx = ++ cnt;
ls[nx] = ls[ox]; rs[nx] = rs[ox];
if(L == R){
seg[nx] = Node(-, -, -);
return;
}
int mid = L + R >> ;
if(pos <= mid) change(ls[nx], ls[ox], L, mid, pos);
else change(rs[nx], rs[ox], mid + , R, pos);
pushup(nx);
}
inline Node query(int x, int L, int R, int l, int r){
if(!x || l > r) return Node();
if(l <= L && R <= r) return seg[x];
int mid = L + R >> ;
if(r <= mid) return query(ls[x], L, mid, l, r);
else if(mid < l) return query(rs[x], mid + , R, l, r);
else return query(ls[x], L, mid, l, r) + query(rs[x], mid + , R, l, r);
}
inline int solve(int a, int b, int c, int d){
int l = , r = n, mid, tmp;
while(l <= r){
mid = l + r >> ;
tmp = query(root[mid], , n, a, b).rmax + query(root[mid], , n, b + , c - ).sum + query(root[mid], , n, c, d).lmax;
if(tmp >= ) l = mid + ;
else r = mid - ;
}
return id[r];
}
int main(){
scanf("%d", &n);
for(Rint i = ;i <= n;i ++){
scanf("%d", a + i); id[i] = i;
}
sort(id + , id + n + , [](int x, int y) -> bool {return a[x] < a[y];});
build(root[], , n);
for(Rint i = ;i < n;i ++)
change(root[i + ], root[i], , n, id[i]);
scanf("%d", &Q);
while(Q --){
for(Rint i = ;i < ;i ++){
scanf("%d", q + i);
q[i] = (q[i] + lans) % n + ;
}
sort(q, q + );
printf("%d\n", lans = a[solve(q[], q[], q[], q[])]);
}
}

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

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

    题目很好,考察对主席树的深入理解与灵活运用. 首先看看一般解决中位数的思路,我们二分一个 \(mid\),将区间中 \(\ge mid\) 的数置为 \(1\),小于的置为 \(-1\),然后求区间和 ...

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

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

  3. [国家集训队]middle

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

  4. P2839 [国家集训队]middle

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

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

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

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

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

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

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

  8. 解题:国家集训队 Middle

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

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

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

随机推荐

  1. HTML5学习笔记(二十九):Cookie和Session

    HTTP协议本身是无状态的,这和HTTP最初的设计是相符的,每次请求都是创建一个短连接,发送请求,得到数据后就关闭连接.即每次连接都是独立的一次连接. 这样的话,导致的问题就是当我在一个页面登陆了账号 ...

  2. 【CFD之道】2018年原创文章汇总

    以下是公众号CFD之道2018年的全部原创文章,共计210篇. 1 Fluent验证案例[60篇] Fluent验证案例02:通过均匀热通量管道层流流动 Fluent验证案例03:管道中湍流流动压降计 ...

  3. 如何关闭windows server2012 80端口

    Windows Server禁用本地端口的两种方法 这篇文章主要介绍了Windows Server 2008 禁用本地端口的两种方法,本文讲解了通过Windows防火墙禁用端口.通过IP安全策略禁用端 ...

  4. 解决space-between最后一排问题

    display:flex + justify-content: space-between 能够实现2端对齐的布局,这种布局在网页中很常见.不过这种布局方式有一个问题.举个例子,我们假设现在一排放4个 ...

  5. python 字符编码判断 chardet评测

    之前一直想找到一个模块,针对字符判断是什么字符集编码的库 网上有chardet的blog,发现自己的环境有这个库,于是就做了测试 >>> import chardet >> ...

  6. IntelJ idea下lombok 不生效的问题(@Builder等注解不生效的问题)解决,lombok Plugin插件安装

    插件安装方式,在设置setting 中找到plugins.在检索框中检索lom,没有的话点击红框内的search in repositories. 点击install进行安装. 记得安装好了重启ide ...

  7. macbook air 2012 mid 安装 windows10 双系统遇到错误 no bootable device insert boot disk and press any key

    macbook型号:air 2012 mid 当前操作系统:mojave 安装工具:boot camp assistant 要安装的双系统:windows 10家庭版 安装教程:百度搜一堆 安装过程中 ...

  8. 在windows 上自动重启 tomcat 的方法

    在windows 上自动重启 tomcat 的方法 实现思路: Windows 上监控tomcat 进程并且自动重启的脚本 一类是 定时重启 tomcat 一类是 监控并重启 写一个守护tomcat进 ...

  9. HAWQ配置之客户端访问

    一.配置简单的口令访问 1,建立数据库和用户 postgres=# create database epbd; CREATE DATABASE postgres=# create role user1 ...

  10. CustomDrawableTextView

    public class CustomDrawableTextView extends TextView{ //image width.height private int imageWidth; p ...