【BZOJ2653】middle(主席树,二分)
题意:一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
给你一个长度为n的序列s。
回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。
位置也从0开始标号。
我会使用一些方式强制你在线。
n<=20000,Q<=25000
思路:RYZ上课讲的题,第一次做这种类型的主席树,以前只会序列第K大,树上第K大,维护二维前缀和之类的……
这道题的精髓是用主席树保存每个点被更改后的N个版本
对于一段区间与一个数X,如果区间中的数a[i]>=x则b[i]=1,否则-1
易得:若某一段中b[i]总和>=0则必定可以从其中取出一段中位数为X的序列,则X可以作为答案
反之显然答案具有单调性,子段和最大的一段一定可以构造出最大的中位数
查询时判断queryr(a,b)+querysum(b+1,c-1)+queryl(c,d)是否>=0即可
剩下的二分X与最大子段和,最大左右子段和维护部分已经在各种各样的地方(NOI Plus模拟赛)做了不下10遍了
而且还有各种写法不同难度的,比如暴力,RMQ之类的
这题就是单点修改+线段树版本的
强制从0开始标号P党表示不爽
var t:array[..,..]of longint;
root,lx,rx,sum:array[..]of longint;
a,b,d:array[..]of longint;
n,que,i,j,cnt,l,r,last,lastans,mid:longint; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
i:=l; j:=r; mid:=a[(l+r)>>];
repeat
while mid>a[i] do inc(i);
while mid<a[j] do dec(j);
if i<=j then
begin
swap(a[i],a[j]);
swap(b[i],b[j]);
inc(i); dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end; procedure sort;
var i,j:longint;
begin
for i:= to do
for j:= to -i do
if d[j]>d[j+] then swap(d[j],d[j+]);
end; procedure pushup(p:longint);
var l,r:longint;
begin
l:=t[p,]; r:=t[p,];
lx[p]:=max(lx[l],sum[l]+lx[r]);
rx[p]:=max(rx[r],sum[r]+rx[l]);
sum[p]:=sum[l]+sum[r];
end; procedure build(var p:longint;l,r:longint);
var mid:longint;
begin
inc(cnt); p:=cnt;
if l=r then
begin
lx[p]:=; rx[p]:=; sum[p]:=;
exit;
end;
mid:=(l+r)>>;
build(t[p,],l,mid);
build(t[p,],mid+,r);
pushup(p);
end; procedure update(l,r:longint;var p:longint;v,x:longint);
var mid:longint;
begin
inc(cnt); t[cnt]:=t[p]; lx[cnt]:=lx[p]; rx[cnt]:=rx[p]; sum[cnt]:=sum[p];
p:=cnt;
if l=r then
begin
sum[p]:=x; lx[p]:=x; rx[p]:=x;
exit;
end;
mid:=(l+r)>>;
if v<=mid then update(l,mid,t[p,],v,x)
else update(mid+,r,t[p,],v,x);
pushup(p);
end; function querysum(l,r,x,y,p:longint):longint;
var mid,s:longint;
begin
if (l=x)and(r=y) then exit(sum[p]);
mid:=(l+r)>>;
s:=;
if y<=mid then s:=querysum(l,mid,x,y,t[p,])
else if x>mid then s:=querysum(mid+,r,x,y,t[p,])
else s:=querysum(l,mid,x,mid,t[p,])+
querysum(mid+,r,mid+,y,t[p,]);
exit(s);
end; function queryleft(l,r,x,y,p:longint):longint;
var mid,s:longint;
begin
if (l=x)and(r=y) then exit(lx[p]);
mid:=(l+r)>>;
s:=;
if y<=mid then s:=queryleft(l,mid,x,y,t[p,])
else if x>mid then s:=queryleft(mid+,r,x,y,t[p,])
else s:=max(queryleft(l,mid,x,mid,t[p,]),
querysum(l,mid,x,mid,t[p,])+
queryleft(mid+,r,mid+,y,t[p,]));
exit(s);
end; function queryright(l,r,x,y,p:longint):longint;
var mid,s:longint;
begin
if (l=x)and(r=y) then exit(rx[p]);
mid:=(l+r)>>;
s:=;
if y<=mid then s:=queryright(l,mid,x,y,t[p,])
else if x>mid then s:=queryright(mid+,r,x,y,t[p,])
else s:=max(queryright(mid+,r,mid+,y,t[p,]),
querysum(mid+,r,mid+,y,t[p,])+
queryright(l,mid,x,mid,t[p,]));
exit(s);
end; function isok(k,a,b,c,d:longint):boolean;
var s:longint;
begin
s:=;
if b+<=c- then s:=querysum(,n-,b+,c-,root[k]);
s:=s+queryright(,n-,a,b,root[k]);
s:=s+queryleft(,n-,c,d,root[k]);
exit(s>=);
end; begin read(n);
for i:= to n do
begin
read(a[i]); b[i]:=i;
end;
qsort(,n); build(root[],,n-);
for i:= to n do
begin
root[i]:=root[i-];
update(,n-,root[i],b[i]-,-);
end;
read(que);
for i:= to que do
begin
for j:= to do read(d[j]);
for j:= to do d[j]:=(d[j]+lastans) mod n;
sort;
l:=; r:=n; last:=;
while l<=r do
begin
mid:=(l+r)>>;
if isok(mid,d[],d[],d[],d[]) then begin last:=mid; l:=mid+; end
else r:=mid-;
end;
lastans:=a[last+];
writeln(lastans);
end; end.
【BZOJ2653】middle(主席树,二分)的更多相关文章
- [BZOJ2653]middle 主席树+二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2042 Solved: 1123[Submit][Status][Disc ...
- 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那样统计答案.但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做 ...
- BZOJ 2653: middle 主席树 二分
https://www.lydsy.com/JudgeOnline/problem.php?id=2653 因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和 ...
- 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? ...
随机推荐
- java第九次作业:第九章例题3个
作业1: 例题9.1 制作圆类,根据圆的半径求出周长及面积 package com.swift; //抽象的方法构成类,把属性和方法进行封装 public class Circle { // 两个方面 ...
- ios 检查内存泄露
简介 在IPhone程式开发中,记忆体泄漏(内存泄漏)是个很容易发生的情况,因为IPhone必须自行作记忆体管理.现在的开发者,大多习惯用的.NET或Java的等有垃圾回收机制的开发语言来作开发,因此 ...
- 830. Positions of Large Groups@python
In a string S of lowercase letters, these letters form consecutive groups of the same character. For ...
- windows10锁定屏幕聚焦图片导出
打开运行,输入%LocalAppData%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Ass ...
- C++ STL容器之 map
map 是一种有序无重复的关联容器. 关联容器与顺序容器不同,他们的元素是按照关键字来保存和访问的,而顺序元素是按照它们在容器中的位置保存和访问的. map保存的是一种 key - value 的pa ...
- luogu P2574 XOR的艺术 (线段树)
luogu P2574 XOR的艺术 (线段树) 算是比较简单的线段树. 当区间修改时.\(1 xor 1 = 0,0 xor 1 = 1\)所以就是区间元素个数减去以前的\(1\)的个数就是现在\( ...
- (64)zabbix正则表达式应用
概述 在前面的<zabbix low-level discovery>一文中有filter一项,用于从结果中筛选出你想要的结果,比如我们在filter中填入^ext|^reiserfs则表 ...
- UNIX环境C语言进程控制
一.进程ID 进程ID即是进程标识,每一个进程都会有一个唯一的非负整数来作为它的进程ID. ID为0的进程通常是调度进程,也可称为交换进程,该进程是内核的一部分,不执行硬盘上的程序,因此也被称为系统进 ...
- perl学习之I/O基础
1.从标准输入进行输入<STDIN> 2.从钻石操作符进行输入<> 3.参数调用@ARGV 4.向标准输出进行输出 5.用printf进行格式化输出 1.<STDIN&g ...
- [译]The Python Tutorial#9. Classes
写在前面 本篇文章是<The Python Tutorial>(3.6.1),第九章,类的译文. 9. Classes 与其他编程语言相比,Python的类机制定义类时,最小化了新的语法和 ...