【BZOJ2653】【主席树+二分】middle
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
5
170337785
271451044
22430280
969056313
206452321
3
3 1 0 2
2 3 1 4
3 1 4 0 271451044
271451044
969056313
Sample Output
Hint
0:n,Q<=100
1,...,5:n<=2000
0,...,19:n<=20000,Q<=25000
Source
【分析】
居然wa了一下TAT.
比较简单的题目,按照权值大小初始化一下线段树将其可持久化,对于二分的版本求前缀和的最大最小值减一下看是否大于等于0就可以了。
/*
唐代贾岛
《剑客 / 述剑》
十年磨一剑,霜刃未曾试。
今日把示君,谁有不平事?
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#include <stack>
#define LOCAL
const int INF = 0x7fffffff;
const int MAXN = + ;
const int maxnode = * + * ;
const int maxm= * + ;
using namespace std;
struct DATA{
int num;
int order;
bool operator < (const DATA &b)const{
return num < b.num;
}
}sorted[MAXN];
int data[MAXN];
struct Node{
int l, r;
int Max, val, sum, Min;
Node *ch[];
}*root[MAXN], mem[maxnode];
int tot, n; Node *NEW(int l, int r){
Node *p = &mem[tot++];
p->l = l;
p->r = r;
p->val = p->sum = p->Max = p->Min = ;
p->ch[] = p->ch[] = NULL;
return p;
}
void update(Node *&t){
if (t->l == t->r) return;
t->sum = ;
if (t->ch[] != NULL) t->sum += t->ch[]->sum;
if (t->ch[] != NULL) t->sum += t->ch[]->sum; t->Max = max(t->ch[]->Max + t->ch[]->sum, t->ch[]->Max);
t->Min = min(t->ch[]->Min + t->ch[]->sum, t->ch[]->Min);
return;
}
void build(Node *&t, int l, int r){
if (t == NULL){
t = NEW(l, r);
}
if (l == r) return;
int mid = (l + r) >> ;
build(t->ch[], l, mid);
build(t->ch[], mid + , r);
update(t);
}
//将l改为-1
void change(Node *&t, Node *&last, int l){
if (t == NULL){
t = NEW(last->l, last->r);
t->val = last->val;
t->Max = last->Max;
t->Min = last->Min;
t->sum = last->sum;
}
if (t->l == l && t->r == l){
t->Min = t->Max = t->sum = -;
return;
}
int mid = (t->l + t->r) >> ;
if (l <= mid){
change(t->ch[], last->ch[], l);
t->ch[] = last->ch[];
}else{
change(t->ch[], last->ch[], l);
t->ch[] = last->ch[];
}
update(t);
}
int qSum(Node *t, int l, int r){
if (l > r) return ;
if (l == ) return qSum(t, l + , r); if (l <= t->l && t->r <= r) return t->sum;
int mid = (t->l + t->r) >>;
int sum = ;
if (l <= mid) sum += qSum(t->ch[], l, r);
if (r > mid) sum += qSum(t->ch[], l, r);
return sum;
}
int qMax(Node *t, int l, int r, int k){
if (l == ) return max(, qMax(t, l + , r, k)); if (l <= t->l && t->r <= r) return t->Max + qSum(root[k], , t->l - );
int mid = (t->l + t->r) >> ;
int Ans = -INF;
if (l <= mid) Ans = max(Ans, qMax(t->ch[], l, r, k));
if (r > mid) Ans = max(Ans, qMax(t->ch[], l, r, k));
return Ans;
}
int qMin(Node *t, int l, int r, int k){
if (l == ) return min(, qMin(t, l + , r, k)); if (l <= t->l && t->r <= r) return t->Min + qSum(root[k], , t->l - );
int mid = (t->l + t->r) >> ;
int Ans = INF;
if (l <= mid) Ans = min(Ans, qMin(t->ch[], l, r, k));
if (r > mid) Ans = min(Ans, qMin(t->ch[], l, r, k));
return Ans;
} void init(){
scanf("%d", &n);
for (int i = ; i <= n; i++){
sorted[i].order = i;
scanf("%d", &sorted[i].num);
data[i] = sorted[i].num;
}
//离散化
sort(sorted + , sorted + + n); tot = ;
root[] = NULL;
build(root[], , n);
//开始可持久化
for (int i = ; i <= (n + ); i++) change(root[i], root[i - ], sorted[i - ].order);
//printf("%d", root[6]->Max);
/*int cnt = 0;
for (int i = 1; i <= n; i++){
if (i == 0 || sorted[i].num != sorted[i - 1].num) cnt++;
rem[cnt] = sorted[i].num;
data[sorted[i].order] = cnt;
}*/
//for (int i = 1; i <= n; i++)
}
int search(int a, int b, int c, int d){
int Ans, l = , r = n;
while (l <= r){
int mid = (l + r) >> ;
if ((qMax(root[mid], c, d, mid) - qMin(root[mid], a, b, mid)) >= ) Ans = mid, l = mid + ;
else r = mid - ;
}
return Ans;
}
void work(){
int last_ans = , m;
scanf("%d", &m);
for (int i = ; i <= m; i++){
int q[];
for (int j = ; j <= ; j++){
scanf("%d", &q[j]);
q[j] = (q[j] + last_ans) % n;
}
sort(q + , q + + );
int a = q[], b = q[], c = q[], d = q[];
a++;c++;
b++;d++;
//printf("%d", qMax(root[5], 3, 3, 5));
//printf("%d%d%d%d\n", a, b, c, d);
last_ans = sorted[search(a - , b - , c, d)].num;
printf("%d\n", last_ans);
}
} int main (){ init();
work();
return ;
}
【BZOJ2653】【主席树+二分】middle的更多相关文章
- 2018湘潭邀请赛C题(主席树+二分)
题目地址:https://www.icpc.camp/contests/6CP5W4knRaIRgU 比赛的时候知道这题是用主席树+二分,可是当时没有学主席树,就连有模板都不敢套,因为代码实在是太长了 ...
- BZOJ.1926.[SDOI2010]粟粟的书架(前缀和 主席树 二分)
题目链接 题意: 在给定矩形区域内找出最少的数,满足和>=k.输出数的个数.两种数据范围. 0~50 注意到(真没注意到...)P[i,j]<=1000,我们可以利用前缀和预处理. num ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- HDU - 4866 主席树 二分
题意:在x轴\([1,X]\)内的上空分布有n个占据空间\([L_i,R_i]\),高度\(D_i\)的线段,射中线段的得分为其高度,每次询问从x轴的\(x\)往上空射的最近k个线段的总得分,具体得分 ...
- POJ 6621: K-th Closest Distance(主席树 + 二分)
K-th Closest Distance Time Limit: 20000/15000 MS (Java/Others) Memory Limit: 524288/524288 K (Jav ...
- HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)
HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分) 传送门:http://acm.hdu.edu.cn/showproblem.php? ...
- [BZOJ2653]middle 主席树+二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2042 Solved: 1123[Submit][Status][Disc ...
- 【bzoj2653】【middle】【主席树+二分答案】
Description 一个长度为 n 的序列 a ,设其排过序之后为 b ,其中位数定义为 b[n/2] ,其中 a,b 从 0 开始标号 , 除法取下整. 给你一个长度为 n 的序列 s .回答 ...
- bzoj 2653: middle (主席树+二分)
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2522 Solved: 1434[Submit][Status][Disc ...
- BZOJ 2653: middle(主席树+二分答案)
传送门 解题思路 首先可以想到一种暴力做法,就是询问时二分,然后大于等于这个值的设为1,否则设为-1,然后就和GSS1那样统计答案.但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做 ...
随机推荐
- 初遇ping++
运行遇到的bug java.lang.NoClassDefFoundError: Failed resolution of: Lcom/pingplusplus/android/PingppLog; ...
- VS 2010不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件
打开VS后不显示头文件源文件和所有以前分类的文件夹,*.h 和*.cpp都显示在同一个文件 点击右图红色指示显示所有文件夹按钮,就能恢复.
- mac下的改装人生——mbp拆卸的各种资源整理
这几天弄了好多的mac上硬件的问题,我自己的mac也被我拆了3次,感觉自己终于跟硬件扯上关系了哈. 在这里放一些我找到比较好的资源教程,供大家学习,如果我以后还需要继续拆我的macbook,我也会回来 ...
- MySQL Workbench类型之MySQL客户端工具的下载、安装和使用
本博文的主要内容有 .MySQL Workbench的下载 .MySQL Workbench的安装 .MySQL Workbench的使用 个人推荐,比较好的MySQL客户端工具 注意啊! 对于noi ...
- 超级好用的国际汇兑平台--Transferwise
一年的CSC留学快结束了,手里还剩了些积攒下来的美元.就国内那点博士的工资,出来一趟好不容易领了点美元可不想都给银行汇兑的手续费给吞了去. 这两天英国退欧,英镑大跌,美元有涨,是个把手里的美元寄回国换 ...
- 使用FileSystemWatcher监视文件变化
本文转载:http://www.cnblogs.com/zanxiaofeng/archive/2011/01/08/1930583.html FileSystemWatcher基础 属性: Path ...
- iOS开发中关于UIImage的知识点总结
UIImage是iOS中层级比较高的一个用来加载和绘制图像的一个类,更底层的类还有 CGImage,以及iOS5.0以后新增加的CIImage.今天我们主要聊一聊UIImage的三个属性: image ...
- 实战DeviceIoControl 之中的一个:通过API訪问设备驱动程序
P.bhw98 { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 9pt; PADDING-BOTTOM: 0px; MARGIN: 10px 0 ...
- Java语言基础(五)
Java语言基础(五) 一.浮点数 浮点数就是小数,其标准是IEEE 754,用指数和尾数表示 例如30000=3*10000=3*10^4 其中4是指数,3是尾数 Java中,浮点数有float ...
- JMeter 使用
Jmeter工具和其他性能工具在原理上完全一致,工具包含4个部分: (1)负载发生器:用于产生负载,通常以多线程或是多进程的方式模拟用户行为. (2)用户运行器:通常是一个脚本运行引擎,用户运行器附加 ...