middle

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1981  Solved: 1097
[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

 
题解:
  十分经典啊,好题,中位数的题目,以后可以想到二分去解决。
  就是比中位数大的变1,小的为-1,则sum>=0即可判断是否可以比当前二分的
  中位数更大,然后就可以,所以对于从小到大,开n个不同状态的线段树,这样就可以了。
 #include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio> #define lson tr[p].ls
#define rson tr[p].rs
#define N 20007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,sz,ans;
int a[N],id[N],rt[N];
struct Node
{
int sum,lmx,rmx,ls,rs;
}tr[N*]; bool cmp(int x1,int x2)
{
return a[x1]<a[x2];
}
void update(int p)
{
tr[p].sum=tr[lson].sum+tr[rson].sum;
tr[p].lmx=max(tr[lson].lmx,tr[lson].sum+tr[rson].lmx);
tr[p].rmx=max(tr[rson].rmx,tr[rson].sum+tr[lson].rmx);
}
void build(int &p,int l,int r)
{
p=++sz;
if (l==r)
{
tr[p].sum=tr[p].lmx=tr[p].rmx=;
return;
}
int mid=(l+r)>>;
build(tr[p].ls,l,mid),build(tr[p].rs,mid+,r);
update(p);
}
void build_new(int yl,int l,int r,int &xz,int val,int z)
{
xz=++sz;tr[xz]=tr[yl];
if (l==r)
{
tr[xz].lmx=tr[xz].rmx=tr[xz].sum=val;
return;
}
int mid=(l+r)>>;
if (z<=mid) build_new(tr[yl].ls,l,mid,tr[xz].ls,val,z);
else build_new(tr[yl].rs,mid+,r,tr[xz].rs,val,z);
update(xz);
}
int get_sum(int p,int l,int r,int x,int y)
{
if (l==x&&r==y) return tr[p].sum;
int mid=(l+r)>>;
if (y<=mid) return get_sum(tr[p].ls,l,mid,x,y);
else if (x>mid) return get_sum(tr[p].rs,mid+,r,x,y);
else return get_sum(tr[p].ls,l,mid,x,mid)+get_sum(tr[p].rs,mid+,r,mid+,y);
}
int get_rx(int p,int l,int r,int x,int y)
{
if (l==x&&r==y) return tr[p].lmx;
int mid=(l+r)>>;
if (y<=mid) return get_rx(tr[p].ls,l,mid,x,y);
else if (x>mid) return get_rx(tr[p].rs,mid+,r,x,y);
else return max(get_rx(tr[p].ls,l,mid,x,mid),get_sum(tr[p].ls,l,mid,x,mid)+get_rx(tr[p].rs,mid+,r,mid+,y));
}
int get_lx(int p,int l,int r,int x,int y)
{
if (l==x&&r==y) return tr[p].rmx;
int mid=(l+r)>>;
if (y<=mid) return get_lx(tr[p].ls,l,mid,x,y);
else if (x>mid) return get_lx(tr[p].rs,mid+,r,x,y);
else return max(get_lx(tr[p].rs,mid+,r,mid+,y),get_sum(tr[p].rs,mid+,r,mid+,y)+get_lx(tr[p].ls,l,mid,x,mid));
}
bool check(int k,int a,int b,int c,int d)
{
int sum=;
if (b+<=c-) sum+=get_sum(rt[k],,n,b+,c-);
sum+=get_lx(rt[k],,n,a,b);
sum+=get_rx(rt[k],,n,c,d);
return sum>=;//大的个数多的话那么可以找更大的中位数、
}
int main()
{
n=read();
for (int i=;i<=n;i++)
a[i]=read(),id[i]=i;
sort(id+,id+n+,cmp);
build(rt[],,n);
for (int i=;i<=n;i++)
build_new(rt[i-],,n,rt[i],-,id[i-]);
int qz[];
m=read();
while(m--)
{
qz[]=read(),qz[]=read(),qz[]=read(),qz[]=read();
for (int i=;i<=;i++)
qz[i]=(qz[i]+ans)%n;
for (int i=;i<=;i++)
qz[i]+=;
sort(qz+,qz++);
int l=,r=n,mid;
while(l<r)
{
mid=(l+r+)>>;
if (check(mid,qz[],qz[],qz[],qz[])) l=mid;
else r=mid-;
}
ans=a[id[l]];
printf("%d\n",ans);
}
}

bzoj 2653 middle (可持久化线段树)的更多相关文章

  1. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  2. BZOJ 2653 middle (可持久化线段树+中位数+线段树维护最大子序和)

    题意: 左端点在[a,b],右端点在[c,d],求这个线段里中位数(上取整)最大值 思路: 对数组离散化,对每一个值建中位数的可持久化线段树(有重复也没事),就是对于root[i],大于等于i的值为1 ...

  3. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  4. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

  5. 【Codechef FRBSUM】【FJOI2016】【BZOJ4299】【BZOJ 4408】 可持久化线段树

    4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 475  Solved: 287[Submit][Status ...

  6. 【bzoj2653】middle 可持久化线段树区间合并

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

  7. BZOJ - 3123 森林 (可持久化线段树+启发式合并)

    题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...

  8. bzoj 3653: 谈笑风生 可持久化线段树

    题目大意 在一棵单位边权的有根树上支持询问: 给定a,k求满足下列条件的有序三元对的个数. a,b,c互不相同 a,b均为c的祖先 a,b树上距离<=k 题解 solution 1 首先我们知道 ...

  9. bzoj 2653 middle 二分答案 主席树判定

    判断中位数是否可行需要将当前的解作为分界,大于其的置为1,小于为-1,然后b-c必选,ab,cd可不选,这个用线段树判定就好 但不能每次跑,所以套主席树,按权值排序,构建主席树,更新时将上一个节点改为 ...

  10. bzoj 2653 二分答案+可持久化线段树

    首先离散化,然后我们知道如果对于一个询问的区间[l1,r1],[l2,r2],我们二分到一个答案x,将[l1,r2]区间中的元素大于等于x的设为1,其余的设为-1,那么如果[l1,r1]的最大右区间和 ...

随机推荐

  1. 如何移除EditText自动焦点

    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_cont ...

  2. C#委托的用法 在C#中我想在一个方法中调用另一个按钮的事件,怎样来实现?

    最开始我也不清楚,后来我是这样想了. 1.事件和委托不是一个概念,你如果是调用control的事件,可以直接在其对应的事件eventhandler上attach自己的事件方法就好了如:this.But ...

  3. 前端组件化(二):优化 DOM 操作

    看看上一节我们的代码,仔细留意一下 changeLikeText 函数,这个函数包含了 DOM 操作,现在看起来比较简单,那是因为现在只有 isLiked 一个状态.由于数据状态改变会导致需要我们去更 ...

  4. Android开发学习——android反编译

    第一种: 1.下载下边的三个jar包,对dex2jar和jd-gui进行解压 2.将需要反编译的apk后缀名改为.rar,然后进行解压 3.将解压后生成的classes.dex加入第一步解压后的dex ...

  5. [BZOJ2809][Apio2012]dispatching 贪心+可并堆

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 我们考虑以每一个节点作为管理者所得的最优答案,一定是优先选择所要薪水少的忍者.那么首 ...

  6. 让px单位自动转换为rem的方法

    开发工具:      编辑器:vscode;     css预处理器:less;(无具体要求): 步骤:   1. vscode安装cssrem插件:   2. 修改css插件的默认配置,其默认转换p ...

  7. Hadoop YARN学习监控JVM和实时监控Ganglia、Ambari(5)

    Hadoop YARN学习监控JVM和实时监控Ganglia.Ambari(5) 1.0 监控ResourceManager进程Java虚拟机中堆空间的特定部分. jstat工具,在JDK的bin目录 ...

  8. core\stm32f10x.h(244): error: #67: expected a "}"

  9. H.264学习笔记2——帧内预测

    帧内预测:根据经过反量化和反变换(没有进行去块效应)之后的同一条带内的块进行预测. A.4x4亮度块预测: 用到的像素和预测方向如图: a~f是4x4块中要预测的像素值,A~Q是临块中解码后的参考值. ...

  10. sql创建发送邮件账号

    ALTER PROCEDURE dbo.sx_pro_autoEmail_account AS begin Declare @my_profile_name varchar(50) Declare @ ...