2653: middle

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2042  Solved: 1123
[Submit][Status][Discuss]

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

我们二分中位数,对于大于mid的数赋值为1,小于mid的数为-1。若最大的区间和大于0则可行。

考虑建一颗主席树(维护权值线段树),root[i]为中位数为i时的前缀树。

二分查询即可。

 #include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define maxn 20005
#define ls(i) t[i].s[0]
#define rs(i) t[i].s[1]
using namespace std;
int read() {
int x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-;
for(;isdigit(ch);ch=getchar()) x=x*+ch-'';
return x*f;
}
struct tmp {
int v,id;
bool operator <(const tmp tt) const {return v<tt.v;}
}a[maxn];
struct data {
int lm,rm,sum,s[];
}t[maxn*];
int n,q,sz;
int root[maxn];
void pushup(int x) {
t[x].lm=max(t[ls(x)].lm,t[ls(x)].sum+t[rs(x)].lm);
t[x].rm=max(t[rs(x)].rm,t[rs(x)].sum+t[ls(x)].rm);
t[x].sum=t[rs(x)].sum+t[ls(x)].sum;
}
void build(int &rt,int l,int r) {
rt=++sz;
if(l==r) {t[rt].sum=t[rt].lm=t[rt].rm=;return;}
int mid=l+r>>;
build(ls(rt),l,mid);build(rs(rt),mid+,r);
pushup(rt); }
void update(int p,int &rt,int l,int r,int x) {
rt=++sz;
t[rt]=t[p];
if(l==r) {t[rt].sum=-;t[rt].lm=t[rt].rm=;return;}
int mid=l+r>>;
if(x<=mid) update(ls(p),ls(rt),l,mid,x);
else update(rs(p),rs(rt),mid+,r,x);
pushup(rt);
}
int qs(int rt,int l,int r,int x,int y) {
if(x>y) return ;
if(l>=x&&r<=y) return t[rt].sum;
int mid=l+r>>,ans=;
if(x<=mid) ans+=qs(ls(rt),l,mid,x,y);
if(y>mid) ans+=qs(rs(rt),mid+,r,x,y);
return ans;
}
int ql(int rt,int l,int r,int x,int y) {
if(x>y) return ;
if(l>=x&&r<=y) return t[rt].lm;
int mid=l+r>>,ans=;
if(x<=mid) ans=max(ql(ls(rt),l,mid,x,y),ans);
if(y>mid) ans=max(qs(ls(rt),l,mid,x,mid)+ql(rs(rt),mid+,r,x,y),ans);
return ans;
}
int qr(int rt,int l,int r,int x,int y) {
if(x>y) return ;
if(l>=x&&r<=y) return t[rt].rm;
int mid=l+r>>,ans=;
if(x<=mid) ans=max(qs(rs(rt),mid+,r,mid+,y)+qr(ls(rt),l,mid,x,y),ans);
if(y>mid) ans=max(qr(rs(rt),mid+,r,x,y),ans);
return ans;
}
bool check(int x,int q1,int q2,int q3,int q4) {
int s=qs(root[x],,n-,q2,q3)+ql(root[x],,n-,q3+,q4)+qr(root[x],,n-,q1,q2-);
return s>=;
}
int main() {
t[].sum=t[].lm=t[].rm=;
n=read();
for(int i=;i<n;i++) a[i].v=read(),a[i].id=i;
sort(a,a+n);
build(root[],,n-);
for(int i=;i<n;i++) update(root[i-],root[i],,n-,a[i-].id);
int ans=;
q=read();
for(int i=;i<=q;i++) {
int ask[];
for(int j=;j<=;j++) ask[j]=(read()+ans)%n;
sort(ask+,ask+);
int L=,R=n-;
while(L<=R) {
int mid=L+R>>;
if(check(mid,ask[],ask[],ask[],ask[])) L=mid+;
else R=mid-;
}
ans=a[L-].v;
printf("%d\n",ans);
}
}

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

  1. bzoj 2653: middle (主席树+二分)

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

  2. BZOJ 2653: middle(主席树+二分答案)

    传送门 解题思路 首先可以想到一种暴力做法,就是询问时二分,然后大于等于这个值的设为1,否则设为-1,然后就和GSS1那样统计答案.但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做 ...

  3. BZOJ 2653: middle 主席树 二分

    https://www.lydsy.com/JudgeOnline/problem.php?id=2653 因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和 ...

  4. 2018湘潭邀请赛C题(主席树+二分)

    题目地址:https://www.icpc.camp/contests/6CP5W4knRaIRgU 比赛的时候知道这题是用主席树+二分,可是当时没有学主席树,就连有模板都不敢套,因为代码实在是太长了 ...

  5. BZOJ.1926.[SDOI2010]粟粟的书架(前缀和 主席树 二分)

    题目链接 题意: 在给定矩形区域内找出最少的数,满足和>=k.输出数的个数.两种数据范围. 0~50 注意到(真没注意到...)P[i,j]<=1000,我们可以利用前缀和预处理. num ...

  6. 计蒜客 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 ...

  7. HDU - 4866 主席树 二分

    题意:在x轴\([1,X]\)内的上空分布有n个占据空间\([L_i,R_i]\),高度\(D_i\)的线段,射中线段的得分为其高度,每次询问从x轴的\(x\)往上空射的最近k个线段的总得分,具体得分 ...

  8. POJ 6621: K-th Closest Distance(主席树 + 二分)

    K-th Closest Distance Time Limit: 20000/15000 MS (Java/Others)    Memory Limit: 524288/524288 K (Jav ...

  9. HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

    HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分) 传送门:http://acm.hdu.edu.cn/showproblem.php? ...

随机推荐

  1. 写一篇Hook Driver.

    关于Hook,有一本书讲的比较清楚,最近刚刚看完,<Rootkits: Subverting the Windows Kernel> http://www.amazon.com/Rootk ...

  2. fckeditor的简单使用

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEnco ...

  3. C#中的String.Format方法

    定义String.Format是将指定的String类型的数据中的每个格式项替换为相应对象的值的文本等效项.(1)string p1="xiaomeng";string p2=&q ...

  4. vb常用函数一览表

    常用内部函数 数学函数 函数 功能 示例 结果 说明 Abs(x) 绝对值 Abs(-50.3) 50.3   Exp(x) 自然指数 Exp(2) e^2 e(自然对数的底)的某次方 Fix(x) ...

  5. P2671 求和

    题目描述 一条狭长的纸带被均匀划分出了 nn 个格子,格子编号从 11 到 nn .每个格子上都染了一种颜色 color\_icolor_i 用 [1,m][1,m] 当中的一个整数表示),并且写了一 ...

  6. CCmdUI

    原文链接地址:http://blog.csdn.net/luicha/article/details/6771185 CCmdUI是一个只被使用于ON_UPDATECOMMAND_UI消息的响应函数中 ...

  7. [Leetcode] Convert sorted list to binary search tree 将排好的链表转成二叉搜索树

    ---恢复内容开始--- Given a singly linked list where elements are sorted in ascending order, convert it to ...

  8. 【模拟赛·polyline】

    Input file: polyline.in Output file: polyline.out Time limit: 1s Memory limit: 128M 有若⼲个类似于下⾯的函数: 定义 ...

  9. POJ2253:Frogger(改造Dijkstra)

    Frogger Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 64864   Accepted: 20127 题目链接:ht ...

  10. windows主机控制

    一.开关机控制 using System.Runtime.InteropServices; //注销.关机.重启 class shutdown { [StructLayout(LayoutKind.S ...