题目链接:洛谷

题目大意:给定一个长度为$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$。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define Rint register int
 4 using namespace std;
 5 const int N = 20003;
 6 int n, Q, q[4], lans, a[N], id[N], root[N], ls[N << 5], rs[N << 5], cnt;
 7 struct Node {
 8     int sum, lmax, rmax;
 9     inline Node(int s = 0, int l = 0, int r = 0): sum(s), lmax(l), rmax(r){}
10     inline Node operator + (const Node &o) const {
11         return Node(sum + o.sum, max(lmax, sum + o.lmax), max(o.rmax, o.sum + rmax));
12     }
13 } seg[N << 5];
14 inline void pushup(int x){
15     seg[x] = seg[ls[x]] + seg[rs[x]];
16 }
17 inline void build(int &x, int L, int R){
18     x = ++ cnt;
19     if(L == R){
20         seg[x] = Node(1, 1, 1);
21         return;
22     }
23     int mid = L + R >> 1;
24     build(ls[x], L, mid);
25     build(rs[x], mid + 1, R);
26     pushup(x);
27 }
28 inline void change(int &nx, int ox, int L, int R, int pos){
29     nx = ++ cnt;
30     ls[nx] = ls[ox]; rs[nx] = rs[ox];
31     if(L == R){
32         seg[nx] = Node(-1, -1, -1);
33         return;
34     }
35     int mid = L + R >> 1;
36     if(pos <= mid) change(ls[nx], ls[ox], L, mid, pos);
37     else change(rs[nx], rs[ox], mid + 1, R, pos);
38     pushup(nx);
39 }
40 inline Node query(int x, int L, int R, int l, int r){
41     if(!x || l > r) return Node();
42     if(l <= L && R <= r) return seg[x];
43     int mid = L + R >> 1;
44     if(r <= mid) return query(ls[x], L, mid, l, r);
45     else if(mid < l) return query(rs[x], mid + 1, R, l, r);
46     else return query(ls[x], L, mid, l, r) + query(rs[x], mid + 1, R, l, r);
47 }
48 inline int solve(int a, int b, int c, int d){
49     int l = 1, r = n, mid, tmp;
50     while(l <= r){
51         mid = l + r >> 1;
52         tmp = query(root[mid], 1, n, a, b).rmax + query(root[mid], 1, n, b + 1, c - 1).sum + query(root[mid], 1, n, c, d).lmax;
53         if(tmp >= 0) l = mid + 1;
54         else r = mid - 1;
55     }
56     return id[r];
57 }
58 int main(){
59     scanf("%d", &n);
60     for(Rint i = 1;i <= n;i ++){
61         scanf("%d", a + i); id[i] = i;
62     }
63     sort(id + 1, id + n + 1, [](int x, int y) -> bool {return a[x] < a[y];});
64     build(root[1], 1, n);
65     for(Rint i = 1;i < n;i ++)
66         change(root[i + 1], root[i], 1, n, id[i]);
67     scanf("%d", &Q);
68     while(Q --){
69         for(Rint i = 0;i < 4;i ++){
70             scanf("%d", q + i);
71             q[i] = (q[i] + lans) % n + 1;
72         }
73         sort(q, q + 4);
74         printf("%d\n", lans = a[solve(q[0], q[1], q[2], q[3])]);
75     }
76 }

View Code

转载于:https://www.cnblogs.com/AThousandMoons/p/10630747.html

luogu2839 [国家集训队]middle相关推荐

  1. P2839 [国家集训队]middle(二分 套 主席树)

    P2839 [国家集训队]middle 有一个长度为nnn的序列,有mmm次询问,每次询问a,b,c,da, b, c, da,b,c,d,为l∈[a,b],r∈[c,d]l \in [a, b], ...

  2. 洛谷P2839 [国家集训队]middle(主席树)

    P2839 [国家集训队]middle 我们可以考虑二分中位数 checkcheckcheck 答案,那么我们对于某个值 midmidmid ,把 [l,r][l,r][l,r] 内的所有小于 mid ...

  3. bzoj 2653 洛谷 P2839 [国家集训队] middle

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2381  Solved: 1340 [Submit][Status][Di ...

  4. 可持久化普通线段树 ---- P2839 [国家集训队]middle 可持久化普通线段树 + 二分 求中位数最大值

    题目链接 题目大意: 解题思路: 这个题思路很妙!! 首先我们假设只有一次询问怎么做? 那么我们可以二分出这个最大值midmidmid,然后把大于等于midmidmid设置成111,把小于midmid ...

  5. [bzoj 2653][国家集训队]middle

    传送门 Description 一个长度为\(n\)的序列\(a\),设其排过序之后为\(b\),其中位数定义为\(b[n/2]\),其中\(a,b\)从\(0\)开始标号,除法取下整. 给你一个长度 ...

  6. P2839 [国家集训队]middle

    题面 • 提一下静态区间第k小的nlog2n的做法: 1. 建关于排名的主席树(按排名顺序建树). 2. 二分答案. • 这样做静态区间第k小的虽然有些ZZ,但它的意义在于将线段树   维护的对象改变 ...

  7. P2839 [国家集训队]middle 二分 + 主席树 在值域上建区间

    传送门 文章目录 题意: 思路: 题意: 思路: 我们先解决怎么判断中位数的问题,我们可以二分一个midmidmid,将<mid<mid<mid的值都变成−1-1−1,其他的数都变成 ...

  8. [国家集训队]middle(二分+主席树[中位数思维题])

    文章目录 点击查看 solution code 点击查看 solution 简单口胡一下就跑 考虑二分答案ansansans 区间[x1,x2],x1∈[a,b],x2∈[c,d][x1,x2],x1 ...

  9. [国家集训队]middle

    嘟嘟嘟 有谁能想到这题会用到主席树呢?(不愧是WJMZBMR出的题) 首先考虑如果区间是固定的话,中位数该怎么求. 没错,二分.如果大于当前二分值\(mid\)的数比小于\(mid\)的数多,说明\( ...

最新文章

  1. 2018 中国开源年度报告发布,阿里系独占鳌头
  2. linux自动下载ftp文件夹,Linux 下FTP定时执行批量下载文件
  3. 洛谷 P1028 数的计算
  4. 启动Tomcat的时候遇到错误
  5. linux dns语法检测工具,DNS解析检查工具之nslookup
  6. 使用CodeIgniter
  7. Microsoft宣布为Power BI提供AI模型构建器,关键驱动程序分析和Azure机器学习集成...
  8. 如果生活中没有数学,那么。。。
  9. Window系统下安装Redis
  10. Spring Cloud微服务之模块依赖修改(六)
  11. python写入mysql乱码_python MYsql中文乱码
  12. 如何在ant里import
  13. 创建一个SpringBoot项目(IDEA版本,保姆级教程)
  14. EPLAN p8 安装失败解决办法
  15. Vblog#2 DAY1
  16. 推荐几款优秀的开源博客系统
  17. IntelliJ IDEA 最新注册码(截止到2019年12月12日)
  18. Invalid packaging for parent POM x, must be “pom“ but is “jar“ @
  19. 【周志华机器学习】十二、计算学习
  20. 前端开发规范【范本】

热门文章

  1. python读取字典元素笔记_python学习笔记:字典的使用示例详解
  2. 在计算机硬盘中没有什么,如果在打开计算机后找不到硬盘,应该怎么办?
  3. c语言中freopen函数,fopen和freopen_C中freopen和fopen的区别(用法+详解+区别)
  4. xampp mysql 内存溢出_php - SQLSTATE [HY000] [2002]连接被拒绝 - 堆栈内存溢出
  5. producer send源码_RocketMq系列之Producer顺序消息发送源码分析(四)
  6. python 实现点击右键用某个程序打开功能_4.PYTHON开发利器之使用VS Code进行python程序开发...
  7. 【Chocolatey】查找包
  8. mysql升级回退_Mysql 升级、用户与授权,
  9. easyui js解析字符串_js相关:详解Jquery Easyui的验证扩展
  10. 4g网络什么时候淘汰_5G时代,4G将淘汰?4G手机会不会像2g,突然失去网络