【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

题解:好吧这题不看题解还真的很难想~

首先二分中位数还是挺好像的,但问题是怎么判断一个中位数是否可行。一个中位数mid可行的条件是序列中(≥mid的数的个数)≥(<mid的数的个数),也就是说,我们将比≥mid的数看成1,<mid的数看成-1,那么需要存在一段区间,使得区间和非负。这又和可持久化线段树有什么关系呢?

我们将所有数排序,然后令1-n的初值都是1,然后将n个数从小到大扔到可持久化线段树中去,并将对应位置变成-1,这样就很好的满足了所给条件。现在问题就是如何判断[a,b]-[c,d]中有没有符合条件的区间,只需要对线段树维护区间连续子段和,最大连续前缀子段和,最大后缀子段和,然后搞一搞就行了。(小白逛公园的简化)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=20010;
int n,m,maxx,minn,tot,ans;
struct sag
{
int ls,rs,sum,lm,rm,sm;
}s[maxn*1000];
struct node
{
int num,org;
}p[maxn];
int q[10],rt[maxn];
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int max(int a,int b,int c)
{
return max(max(a,b),c);
}
void pushup(int x)
{
s[x].lm=max(s[s[x].ls].lm,s[s[x].ls].sum+s[s[x].rs].lm,0);
s[x].rm=max(s[s[x].rs].rm,s[s[x].rs].sum+s[s[x].ls].rm,0);
s[x].sm=max(s[s[x].ls].sm,s[s[x].rs].sm,s[s[x].ls].rm+s[s[x].rs].lm);
s[x].sum=s[s[x].ls].sum+s[s[x].rs].sum;
}
void build(int l,int r,int &x)
{
if(!x) x=++tot;
if(l==r)
{
s[x].sum=s[x].sm=s[x].lm=s[x].rm=1;
return;
}
int mid=l+r>>1;
build(l,mid,s[x].ls),build(mid+1,r,s[x].rs);
pushup(x);
}
void insert(int x,int &y,int l,int r,int pos)
{
if(r<pos) return ;
y=++tot;
if(l==r)
{
s[y].sum=-1,s[y].lm=s[y].rm=s[y].sm=0;
return ;
}
int mid=l+r>>1;
if(pos<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,pos);
else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,pos);
pushup(y);
}
bool cmp(node a,node b)
{
return a.num<b.num;
}
int qs(int l,int r,int x,int a,int b)
{
if(a>b) return 0;
if(a<=l&&r<=b) return s[x].sum;
int mid=l+r>>1;
if(b<=mid) return qs(l,mid,s[x].ls,a,b);
if(a>mid) return qs(mid+1,r,s[x].rs,a,b);
return qs(l,mid,s[x].ls,a,b)+qs(mid+1,r,s[x].rs,a,b);
}
int ql(int l,int r,int x,int a,int b)
{
if(a>b) return 0;
if(a<=l&&r<=b) return s[x].rm;
int mid=l+r>>1;
if(b<=mid) return ql(l,mid,s[x].ls,a,b);
if(a>mid) return ql(mid+1,r,s[x].rs,a,b);
return max(ql(l,mid,s[x].ls,a,b)+qs(mid+1,r,s[x].rs,a,b),ql(mid+1,r,s[x].rs,a,b));
}
int qr(int l,int r,int x,int a,int b)
{
if(a>b) return 0;
if(a<=l&&r<=b) return s[x].lm;
int mid=l+r>>1;
if(b<=mid) return qr(l,mid,s[x].ls,a,b);
if(a>mid) return qr(mid+1,r,s[x].rs,a,b);
return max(qr(mid+1,r,s[x].rs,a,b)+qs(l,mid,s[x].ls,a,b),qr(l,mid,s[x].ls,a,b));
}
int solve(int sta)
{
int a=ql(1,n,rt[sta-1],q[0],q[1]-1);
int b=qs(1,n,rt[sta-1],q[1],q[2]);
int c=qr(1,n,rt[sta-1],q[2]+1,q[3]);
if(a+b+c>=0) return 1;
return 0;
}
int main()
{
n=rd();
int i,j,l,r,mid;
for(i=1;i<=n;i++) p[i].num=rd(),p[i].org=i,maxx=max(maxx,p[i].num),minn=min(minn,p[i].num);
build(1,n,rt[0]);
sort(p+1,p+n+1,cmp);
for(i=1;i<=n;i++) insert(rt[i-1],rt[i],1,n,p[i].org);
m=rd();
for(i=1;i<=m;i++)
{
for(j=0;j<4;j++) q[j]=(rd()+ans)%n+1;
sort(q+0,q+4);
l=1,r=n+1;
while(l<r)
{
mid=l+r>>1;
if(solve(mid)) l=mid+1;
else r=mid;
}
ans=p[l-1].num;
printf("%d\n",ans);
}
return 0;
}

【BZOJ2653】middle 二分+可持久化线段树的更多相关文章

  1. BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)

    换markdown写了.. 题意: 给你一个1e5的字符串,1e5组询问,求\([l_1,r_1]\)的所有子串与\([l_2,r_2]\)的lcp 思路: 首先可以发现答案是具有单调性的,我们考虑二 ...

  2. 【XSY2720】区间第k小 整体二分 可持久化线段树

    题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...

  3. bzoj 2653 middle (可持久化线段树)

    middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1981  Solved: 1097[Submit][Status][Discuss] D ...

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

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

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

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

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

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

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

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

  8. 洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)

    有点类似NOI2014购票 首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$ 这个显然是可以斜率优化的... $\frac {f(j)-f(k)}{dep_j ...

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

随机推荐

  1. AnjularJS小项目,小案例,练手,猜数字

    之前自己就学了点AnjularJS,都是在菜鸟教程里面将基础的只是大致过了一遍,没怎么自己动手做什么东西练练手,但还是觉得纸上得来终觉浅,得知此事要躬行啊,今天就做了个猜数字的小游戏,觉得效果还不错, ...

  2. C# 调用bat文件

    引入名称空间: using System.Diagnostics; Process proc = null; try { string targetDir = string.Format(@" ...

  3. selenium2.0 --常用函数2

    新建实例driver = webdriver.Chrome() 1.获取当前页面的Url函数 方法:current_url 实例: driver.current_url 2.获取元素坐标 方法:loc ...

  4. Hive SQL 常见问题(转载)

    http://www.aboutyun.com/thread-14942-1-1.html 问题导读 1.Hive查询语句和SQL查询语句区别与联系. 2.distribute by.group by ...

  5. JAVA Socket 底层是怎样基于TCP/IP 实现的???

    首先必须明确:TCP/IP模型中有四层结构:       应用层(Application Layer).传输层(Transport  Layer).网络层(Internet Layer  ).链路层( ...

  6. deepin linux 15.3安装完eclipse启动报错An error has occurred.

    原因是系统中安装了jdk9 导致的. 卸载jdk9就可以了 $ java -version Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings ...

  7. Github上Fork代码,及源码修改

    iOS开发中经常遇到这种情况,你使用的第三方库不能完全满足自己项目需要,只能修改源码来解决. 我们以前的解决办法是,添加到项目中直接修改源码.这样就有一个问题,不能和源库同步,当作者更新后你不能(po ...

  8. spoj7001 Visible Lattice Points 莫比乌斯反演+三维空间互质对数

    /** 题目:Visible Lattice Points 链接:https://vjudge.net/contest/178455#problem/A 题意:一个n*n*n大小的三维空间.一侧为(0 ...

  9. codeforces 825F F. String Compression dp+kmp找字符串的最小循环节

    /** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: d ...

  10. PHP 表格 post 提交 接受

    <form action="<?php echo site_url('home/order/sned_order'); ?>" method="post ...