题解【bzoj2653 middle】
Description
给你一个序列,每次询问给出四个数 \(a,b,c,d\),求所有区间 \([l,r]\) 满足 \(l \in [a,b], r \in [c,d]\) 的中位数的最大值。强制在线
\(n \leq 20000, Q \leq 25000,a_i \leq 10^9\)
Solution
考虑二分答案。假设现在二分出来的是 \(x\) ,那么把 \(\ge x\) 的位置设成 \(1\) ,\(< x\) 的设为 \(-1\) 。那么一个区间的中位数 \(\ge x\) 等价于这个区间的和 \(\ge 0\)
如何处理题目给的左右端点的限制?
可以发现 \([l,r]\) 必然包含 \([b+1,c-1]\) (如果 \(b+1 \leq c+1\) 的话)所以 \([l, r]\) 的和必然包含 \([b+1, c-1]\) 的和
显然让 \([l,r]\) 的和最大的方案是取 \([a,b]\) 的最大右段和 和 \([c,d]\) 的最大左段和
这些都可以用线段树维护。但这样需要每个数都开一颗线段树,空间爆炸。
把数组排序,这样每个数的线段树显然只是由前一个数的线段树把一个点的权值从 \(1\) 改为 \(-1\) 。可以使用主席树的思想(貌似就是主席树
然后就做完了。复杂度 \(O(m \log^2 n)\)
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 2000;
int n, m; int q[4];
struct Node {
int d, id;
} a[N];
inline bool cmp(Node x, Node y) {
return x.d < y.d;
}
struct node {
int left, right;
int sm, lm, rm;
node *ch[2];
inline void upd() {
sm = ch[0]->sm + ch[1]->sm;
lm = max(ch[0]->lm, ch[0]->sm + ch[1]->lm);
rm = max(ch[1]->rm, ch[1]->sm + ch[0]->rm);
}
} *rt[N], pool[N * 50], *cur = pool, *ans;
inline void B (node *r, int left, int right) {
r->left = left, r->right = right;
if(left == right) { r->sm = r->lm = r->rm = 1; return ; }
node *lson = cur++, *rson = cur++;
int mid = (left + right) >> 1;
r->ch[0] = lson, r->ch[1] = rson;
B(lson, left, mid), B(rson, mid + 1, right); r->upd();
}
inline void I (node *pre, node *now, int pos) {
now->left = pre->left, now->right = pre->right;
if(now->left == now->right) {
now->sm = now->lm = now->rm = -1; return ;
} int mid = (pre->left + pre->right) >> 1;
if(pos <= mid) now->ch[1] = pre->ch[1], I(pre->ch[0], now->ch[0] = cur++, pos);
if(pos > mid) now->ch[0] = pre->ch[0], I(pre->ch[1], now->ch[1] = cur++, pos);
now->upd();
}
inline node* Q (node *now, int l, int r) {
if(now->left == l && now->right == r) return now;
if(now->ch[0]->right >= r) return Q(now->ch[0], l, r);
else if(now->ch[1]->left <= l) return Q(now->ch[1], l, r);
else {
node *ret = cur++, *L, *R;
L = Q(now->ch[0], l, now->ch[0]->right);
R = Q(now->ch[1], now->ch[1]->left, r);
ret->sm = L->sm + R->sm;
ret->lm = max(L->lm, L->sm + R->lm);
ret->rm = max(R->rm, R->sm + L->rm);
return ret;
}
}
inline bool check(int id) {
int sum = 0;
if(q[2] + 1 <= q[3] - 1) sum += Q (rt[id - 1], q[2] + 1, q[3] - 1)->sm;
sum += Q (rt[id - 1], q[1], q[2])->rm;
sum += Q (rt[id - 1], q[3], q[4])->lm;
return sum >= 0;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i].d);
a[i].id = i;
} sort(a + 1, a + n + 1, cmp);
B(rt[0] = cur++, 1, n);
for(int i = 1; i <= n; i++) {
rt[i] = cur++; I(rt[i - 1], rt[i], a[i].id);
}
int ans = 0; scanf("%d", &m);
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= 4; j++) {
scanf("%d", &q[j]),
q[j] += ans, q[j] %= n; q[j]++;
}
sort(q + 1, q + 4 + 1);
int l = 1, r = n;
while(l <= r) {
int mid = (l + r) / 2;
if(check(mid)) l = mid + 1, ans = a[mid].d;
else r = mid - 1;
} printf("%d\n", ans);
}
return 0;
}
题解【bzoj2653 middle】的更多相关文章
- BZOJ2653 middle 【主席树】【二分】*
BZOJ2653 middle Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样 ...
- bzoj2653: middle
首先,对于每个询问,我们二分答案 然后对于序列中大于等于中位数的数,我们把它们置为1,小于中位数的数,置为-1 那么如果一个区间和大于等于0,那么就资磁,否则就不滋磁 这个区间和呢,我们可以用主席树维 ...
- BZOJ2653 middle(二分答案+主席树)
与中位数有关的题二分答案是很常用的trick.二分答案之后,将所有大于它的看成1小于它的看成-1,那么只需要判断是否存在满足要求的一段和不小于0. 由于每个位置是1还是-1并不固定,似乎不是很好算.考 ...
- [BZOJ2653]middle 主席树+二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2042 Solved: 1123[Submit][Status][Disc ...
- BZOJ2653 middle 【二分 + 主席树】
题目 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c ...
- [bzoj2653][middle] (二分 + 主席树)
Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...
- PKUSC2018训练日程(4.18~5.30)
(总计:共66题) 4.18~4.25:19题 4.26~5.2:17题 5.3~5.9: 6题 5.10~5.16: 6题 5.17~5.23: 9题 5.24~5.30: 9题 4.18 [BZO ...
- 算法与数据结构基础 - 链表(Linked List)
链表基础 链表(Linked List)相比数组(Array),物理存储上非连续.不支持O(1)时间按索引存取:但链表也有其优点,灵活的内存管理.允许在链表任意位置上插入和删除节点.单向链表结构一般如 ...
- BZOJ2653:middle——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2653 Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2], ...
随机推荐
- JDK动态代理的简单理解
转载:http://www.cnblogs.com/luotaoyeah/p/3778183.html 动态代理 代理模式是 Java 中的常用设计模式,代理类通过调用被代理类的相关方法,提供预处理. ...
- Shell重新学习(忘光了)
成功和失败都放同一个文件 调试shell
- OO第二阶段作业总结
第五次作业: 设计策略: 本次作业设计的基本思路是按照指导书所给的推荐方法来完成的,即共用对象为队列盘,线程有电梯.调度器.以及扫描器,扫描器将控制台输入的有效指令加入到队列盘中,调度 ...
- alpha版postmortem 报告
一.团队开发存在的问题 此次会议我们团队中每个成员都仔细思考并提出了团队在这一阶段存在的问题,主要如下: 1.前期任务规划.分配不合适: 2.个人对认领任务模块完成度.了解度不够: 3.个人学习意识. ...
- tomcat启动问题排查
遇到tomcat错误时不一定是tomcat的配置问题,还有可能是项目的配置问题.检查下xml的servlet配置是不是出了问题. tomcat8.0使用注解的方式帮我注册了servlet了,这时候已经 ...
- lintcode-513-完美平方
513-完美平方 给一个正整数 n, 找到若干个完全平方数(比如1, 4, 9, ... )使得他们的和等于 n.你需要让平方数的个数最少. 样例 给出 n = 12, 返回 3 因为 12 = 4 ...
- 判断二叉树B是否是树A的子树
如下图所示,则认为树B是树A的子树. 代码如下: /** public class TreeNode { int val = 0; TreeNode left = null; TreeNode rig ...
- Java面试& HashMap实现原理分析
1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O( ...
- CXGRID用法(取行、列值;定位选中某行等等)[转]
Delphi Cxgrid获取选中行列,排序规则,当前正在编辑的单元格内的值 cxGrid1DBTableView1.Controller.FocusedRowIndex 当前行号 cxGrid1DB ...
- 关于.net服务启动注册到zookeeper,但是注册节点20分钟自动消失解决办法
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,作用简单描述就是相当于一个中介,服务提供者将服务注册到zk,服务调用者直接从zk获取,zk的作用就是协调 最近碰到公 ...