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. shell之arp命令

    arp: 显示所有的表项. arp -d address: 删除一个arp表项. arp -s address hw_addr: 设置一个arp表项.   常用参数: -a 使用bsd形式输出.(没有 ...

  2. 解决 vuex mapGetters 语法报错 (Unexpected token )

    在使用vuex2的mapGetters 和 mapActions 的方法时,借助 stage2 的 Object Rest Operator 特性,可以写出下面代码:  computed: { ... ...

  3. TeamWork#1,Week 5,Suggestions for Team Project

    我们团队联系到了我们六班的直系学长,并向他咨询了软件工程基础这门课的团队项目相关的问题.他们团队的名字命名为Z-XML,团队中的几个学长也都是我平时所熟识的.虽然学长已经大四,忙着考研工作等各种事务, ...

  4. 实验1 熟悉Linux开发环境 实验报告

    参见http://www.cnblogs.com/lhc-java/p/4970269.html

  5. 《JavaScript》forEach()和map()

    js中的forEach()方法只能遍历数组,不能遍历字符串和对象,和$.each()有很多使用上的区别array.forEach(funcion(value,index,arr){},thisValu ...

  6. Java导出引用jar包的文件

    安装Eclipse打包插件Fat Jar      方案一对于含有较多第三方jar文件或含有第三方图片资源等就显得不合适,太繁琐.这时可以使用一个打包的插件-Fat Jar.      Fat Jar ...

  7. J2EE 13种技术规范

    J2EE平台由一整套服务(种技术规范进行简单的描述(限于篇幅,这里只能进行简单的描述): 1.JDBC(Java Database Connectivity):    JDBC API为访问不同的数据 ...

  8. [日常工作] 应用服务器上面应该尽量少开各种应用 --Chrome 内存泄露 让应用服务器非常缓慢

    1. 前段时间修改 服务器的密码 导致应用程序的web site 启动有问题 ,打开chrome 查看了错误详细信息 但是忘记关了.. 今天反馈机器非常缓慢 简单看了下内存 吐血... 所以以后不能在 ...

  9. Java机器学习框架deeplearing4j入门教程

    1.添加项目maven添加依赖 or 导入jar包 or 使用jvm <project xmlns="http://maven.apache.org/POM/4.0.0" x ...

  10. 【uoj#213】[UNR #1]争夺圣杯 单调栈+差分

    题目描述 给出一个长度为 $n$ 的序列,对于 $1\sim n$ 的每一个数 $i$ ,求这个序列所有长度为 $i$ 的子区间的最大值之和,输出每一个 $i$ 的答案模 $998244353$ 后异 ...