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】的更多相关文章

  1. BZOJ2653 middle 【主席树】【二分】*

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

  2. bzoj2653: middle

    首先,对于每个询问,我们二分答案 然后对于序列中大于等于中位数的数,我们把它们置为1,小于中位数的数,置为-1 那么如果一个区间和大于等于0,那么就资磁,否则就不滋磁 这个区间和呢,我们可以用主席树维 ...

  3. BZOJ2653 middle(二分答案+主席树)

    与中位数有关的题二分答案是很常用的trick.二分答案之后,将所有大于它的看成1小于它的看成-1,那么只需要判断是否存在满足要求的一段和不小于0. 由于每个位置是1还是-1并不固定,似乎不是很好算.考 ...

  4. [BZOJ2653]middle 主席树+二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2042  Solved: 1123[Submit][Status][Disc ...

  5. BZOJ2653 middle 【二分 + 主席树】

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

  6. [bzoj2653][middle] (二分 + 主席树)

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

  7. 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 ...

  8. 算法与数据结构基础 - 链表(Linked List)

    链表基础 链表(Linked List)相比数组(Array),物理存储上非连续.不支持O(1)时间按索引存取:但链表也有其优点,灵活的内存管理.允许在链表任意位置上插入和删除节点.单向链表结构一般如 ...

  9. BZOJ2653:middle——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2653 Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2], ...

随机推荐

  1. Python 标准库中的装饰器

    题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...

  2. PSP Daily新增功能说明书

    1.选择输入类别时可以记录原来的输入,支持用户选择记录清空功能 2.添加“恢复最近”button,点击这个按钮可以跳出一个页面显示最近的excel记录,用户可以通过勾选相应的excel文件名,恢复选中 ...

  3. Scrum Meeting 11.10

    成员 今日任务 明日计划 用时 徐越  调试前端代码 协助重构UI,完善前端逻辑  2h  赵庶宏 调出不能显示回答列表的bug,是后端数据库建库问题 与前一组进行数据库统一  3h  薄霖 UI代码 ...

  4. 奔跑吧DKY——团队Scrum冲刺阶段-Day 5

    今日完成任务 谭鑫:继续解决背景音乐的问题,修改游戏中的bug. 黄宇塘:背景图片需重做,开始制作人物图片和背景图. 赵晓海:制作人物图及背景图. 方艺雯:制作人物图,编写博客. 王禹涵:继续解决背景 ...

  5. 第二阶段每日站立会议Second Day

    昨天我在手机端安装cpp后进行界面效果测试以及进一步完善 今天对图片显示的大小进行调整 遇到的问题:当图片太小时,显示一块灰色区域,不美观

  6. “吃神么,买神么”的第二个Sprint计划

    “吃神么,买神么”的第二个Sprint计划   一.现状   前台布局设计完成一个主页,可以让浏览者了解我们网站的功能,这是第一个阶段的Spring完成的事情.由于没有实际的功能体现,所以第二阶段开始 ...

  7. “吃神么,买神么”的第一个Sprint计划(第三天)

    “吃神么,买神么”项目Sprint计划 ——5.23  星期六(第三天)立会内容与进度 摘要:今天的立会主要是报告进度以及遇到的困难. 进度:logo正在进行中,其他基本没什么问题.都确定要做出来的大 ...

  8. Head First Java & 继承

  9. Scrum 项目2.0 3.0

    顺带 MY—HR 成员: 角色分配 学号 博客园 团队贡献分 丘惠敏 PM项目经理 201406114203 http://www.cnblogs.com/qiuhuimin/ 19 郭明茵 用户 2 ...

  10. D3.js 入门学习(二) V4的改动

    //d3.scan /* 新的d3.scan方法对数组进行线性扫描,并根据指定的比较函数返回至少一个元素的索引. 这个方法有点类似于d3.min和d3.max. 而d3.scan可以得到极值的索引而不 ...