Description

  一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
  给你一个长度为n的序列s。
  回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
  其中a<b<c<d。
  位置也从0开始标号。
  我会使用一些方式强制你在线。

Input

  第一行序列长度n。
  接下来n行按顺序给出a中的数。
  接下来一行Q。
  然后Q行每行a,b,c,d,我们令上个询问的答案是x(如果这是第一个询问则x=0)。
  令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
  将q从小到大排序之后,令真正的要询问的a=q[0],b=q[1],c=q[2],d=q[3]。
  输入保证满足条件。

Output

  Q行依次给出询问的答案。

Sample Input


Sample Output


HINT

  0:n,Q<=100

  1,...,5:n<=2000

  0,...,19:n<=20000,Q<=25000

Solution

一道神奇的题目,在长沙培训时初次见面

和一般主席树的做法不尽相同

为了避免枚举中位数,我们将序列排序,对排序后的点建立一颗以整个序列编号为节点的线段树

此后,对于每个有序点的线段树,我们将其内的所有值小于它的点的贡献标记为-1,记录从左边起最大连续和,还有从右边起最大连续和

显然,这个排序后的主席树是满足二分性质的

那么,我们二分中位数,查询区间[B,C]的贡献、[A,B)的右边最大连续和、(C,D]的左边最大连续和是否大于或等于0,若是,则说明它可以构成一个合法的中位数是当前二分值的序列,也说明中位数大于或等于当前此数

最后输出二分答案即可

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 20200
#define mid ((s) + (t) >> (1))
#define dmax(a, b) ((a) > (b) ? (a) : (b)) using namespace std; inline int Rin(){
int x = , c = getchar(), f = ;
for(; c < || c > ; c = getchar())
if(!(c ^ ))f = -;
for(; c > && c < ; c = getchar())
x = (x << ) + (x << ) + c - ;
return x * f;
} int n; namespace Arcueid{
struct Area{
int lq, rq, sum; Area(int x = ){
lq = rq = dmax(x, );
sum = x;
}
}; Area operator + (Area a, Area b){
Area c;
c.sum = a.sum + b.sum;
c.lq = dmax(a.lq, a.sum + b.lq);
c.rq = dmax(b.rq, a.rq + b.sum);
return c;
} struct Node{
Node *l, *r;
Area key;
Node(){}
Node(Node *_l, Node *_r, Area _key) : l(_l), r(_r), key(_key) {}
}*_nil = new Node(), *nil = (*_nil = Node(_nil, _nil, ), _nil), pool[N * ], *top = pool, *rt[N];
Node *newnode(Node *_, Node *__, Area ___){
*top = Node(_, __, ___);
return top++;
} Node *born(int s, int t){
if(!(s ^ t))return newnode(0x0, 0x0, Area());
Node *_ = born(s, mid); Node *__ = born(mid + , t);
return newnode(_, __, _->key + __->key);
} Node *real(Node *p, int s, int t, int k){
if(!(s ^ t))return newnode(0x0, 0x0, Area(-));
if(k <= mid){
Node *_ = real(p->l, s, mid, k);
return newnode(_, p->r, _->key + p->r->key);
}
else{
Node *_ = real(p->r, mid + , t, k);
return newnode(p->l, _, p->l->key + _->key);
}
} Area secret(Node *p, int s, int t, int l, int r){
if(l == s && t == r)return p->key;
if(r <= mid)return secret(p->l, s, mid, l, r);
if(l > mid)return secret(p->r, mid + , t, l, r);
return secret(p->l, s, mid, l, mid) + secret(p->r, mid + , t, mid + , r);
} bool judge(int A, int B, int C, int D, int k){
int res = ;
res += secret(rt[k], , n, B, C).sum;
res += secret(rt[k], , n, A, B - ).rq;
res += secret(rt[k], , n, C + , D).lq;
return res >= ;
} int binsearch(int A, int B, int C, int D){
int s = , t = n;
while(s + < t){
if(judge(A, B, C, D, mid))
s = mid;
else
t = mid;
}
if(judge(A, B, C, D, t))
return t;
return s;
}
} namespace moon{
struct dat{
int key, pos; void init(int _) {key = Rin(); pos = _;} bool operator < (const dat h)const{
return key < h.key;
}
}b[N]; void cause(){
n = Rin();
for(int i = ; i <= n; i++)
b[i].init(i);
sort(b + , b + + n);
Arcueid::rt[] = Arcueid::born(, n);
for(int i = ; i <= n; i++)
Arcueid::rt[i] = Arcueid::real(Arcueid::rt[i - ], , n, b[i - ].pos);
int m = Rin(), ans = , q[];
while(m--){
for(int j=;j<;j++)
q[j] = Rin(), q[j] = (q[j] + ans) % n+;
sort(q,q+);
printf("%d\n", ans = b[Arcueid::binsearch(q[],q[],q[],q[])].key);
}
}
} int main(){
moon::cause();
return ;
}

[bzoj2653][middle] (二分 + 主席树)的更多相关文章

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

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

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

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

  3. 【BZOJ2653】Middle(主席树)

    [BZOJ2653]Middle(主席树) 题面 BZOJ 洛谷 Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你 ...

  4. 洛谷P4559 [JSOI2018]列队 【70分二分 + 主席树】

    题目链接 洛谷P4559 题解 只会做\(70\)分的\(O(nlog^2n)\) 如果本来就在区间内的人是不用动的,区间右边的人往区间最右的那些空位跑,区间左边的人往区间最左的那些空位跑 找到这些空 ...

  5. 【BZOJ 4556】[Tjoi2016&Heoi2016]字符串 SAM+二分+主席树

    这道题市面上就两种法:一种是SA+二分+主席树,一种是SAM+二分+主席树(有不少人打线段树合并???)(除此之外还有一种利用炒鸡水的数据的暴力SA,贼快.....)(当时学SA的时候没做这道题,现在 ...

  6. 【BZOJ2653】middle(主席树,二分)

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

  7. 【洛谷2839/BZOJ2653】middle(主席树)

    题目: 洛谷2839 分析: 记\(s_i\)表示原序列中第\(i\)大的数. 考虑对于任意一个区间\([a,b]\),设它的中位数为\(s_m\),那么这个区间内大于等于\(s_m\)的数和小于\( ...

  8. 「BZOJ 2653」middle「主席树」「二分」

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

  9. Codeforces Round #276 (Div. 1) E. Sign on Fence 二分+主席树

    E. Sign on Fence   Bizon the Champion has recently finished painting his wood fence. The fence consi ...

随机推荐

  1. Java:泛型基础

    泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...

  2. 打造android偷懒神器———ListView的万能适配器

    如果你去做任何一个项目,我相信你都会跟我有一样的经历,最最普遍的就是列表显示ListView,当然,写N个自定义的适配器也是情理之中.虽说程序员本身就是搬砖,做这些枯燥无味的重复的事情也是理所当然,但 ...

  3. javaWeb应用打包

    在Java中,使用"jar"命令来对将JavaWeb应用打包成一个War包,jar命令的用法如下:

  4. 网络爬虫:使用Scrapy框架编写一个抓取书籍信息的爬虫服务

      上周学习了BeautifulSoup的基础知识并用它完成了一个网络爬虫( 使用Beautiful Soup编写一个爬虫 系列随笔汇总 ), BeautifulSoup是一个非常流行的Python网 ...

  5. <Node入门经典>读书笔记

    最近在读<Node入门经典>, 之前没有做笔记, 今天开始把看过自己又写了的代码放这里以免忘记. express var express = require('express') var ...

  6. 翻译:使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 2

    我们的目标: 需求 Screen 1: 联系人列表 - 查看所有联系人 1.1 这个 screen 将显示数据库中的所有联系人. 1.2 用户可以删除任何联系人.1.3 用户可以编辑任何联系人的详细信 ...

  7. Python ZIP 文件创建与读取

    Automate the Boring Stuff 学习笔记 02 Python 内置的 zipfile 模块可以对文件(夹)进行ZIP格式的压缩和读取操作.要进行相关操作,首先需要实例化一个 Zip ...

  8. Cobar + MySQL 技术验证(li)

    一.简介 Cobar是一个对数据进行拆分后进行分布式存储的产品,可以支持使用后台的 MySQL或者Oracle数据库,通过配置,将数据按照一定规则存储入不同的数据库中.即用分布式数据库代替了集中式数据 ...

  9. Atitit.ide技术原理与实践attilax总结

    Atitit.ide技术原理与实践attilax总结 1.1. 语法着色1 1.2. 智能提示1 1.3. 类成员outline..func list1 1.4. 类型推导(type inferenc ...

  10. Struts2入门(七)——Struts2的文件上传和下载

    一.前言 在之前的随笔之中,我们已经了解Java通过上传组件来实现上传和下载,这次我们来了解Struts2的上传和下载. 注意:文件上传时,我们需要将表单提交方式设置为"POST" ...