博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ]2653: middle
阅读量:4502 次
发布时间:2019-06-08

本文共 2802 字,大约阅读时间需要 9 分钟。

Time Limit: 20 Sec  Memory Limit: 512 MB

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

Sample Output

  271451044
  271451044
  969056313

HINT

  0:n,Q<=100

  1,...,5:n<=2000
  0,...,19:n<=20000,Q<=25000

Solution

  原题题面有毒,稍微改了改一些会影响到题意理解的描述,如果看不懂BZOJ上的题意就看一看这里的吧……

  然后是题解。对每次询问我们考虑二分答案,如果存在一个左端点在[a,b]内,右端点在[c,d]内的连续子序列,满足子序列内大等于当前二分出的答案的数的个数不少于小于该答案的数的个数,那么最大答案一定不会小于该答案,现在假设我们确定了这个答案,我们把大等于该答案的数设为1,小于该答案的数设成-1,那么可以转化为求最大子段和,自然想到用线段树维护这些1和-1的前缀和,用[c,d]中最大的前缀和减去[a-1,b-1]中最小的前缀和,如果大等于0即check成功。但我们不能对每个值都建这样一棵线段树,我们发现第k大的数对应的线段树相比第k+1大的数的线段树,只有一个1变成了-1,于是我们从小到大加入这些数,用可持久化线段树维护区间减(因为我们维护的是前缀和)和区间最值即可,总复杂度O(nlogn+qlogn^2)。

Code

#include
#include
using namespace std;inline int read(){ int x;char c; while((c=getchar())<'0'||c>'9'); for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0'; return x;}#define MN 20000#define ND 900000struct node{
int l,r,mn,mx,mk;}t[ND+5];int a[MN+5],c[MN+5],rt[MN+5],tn;bool cmp(int x,int y){
return a[x]
>1; t[p].mn=l;t[p].mx=r; if(l
>1; if(l==L)return mark(p,-2); if(L>mid)t[p].r=dec(t[p].r,mid+1,r,L); else t[p].l=dec(t[p].l,l,mid,L),t[p].r=dec(t[p].r,mid+1,r,mid+1); return up(p),p;}int qmn(int k,int l,int r,int L,int R,int mk){ if(l==L&&r==R)return t[k].mn+mk; int mid=l+r>>1;mk+=t[k].mk; if(R<=mid)return qmn(t[k].l,l,mid,L,R,mk); if(L>mid)return qmn(t[k].r,mid+1,r,L,R,mk); return min(qmn(t[k].l,l,mid,L,mid,mk),qmn(t[k].r,mid+1,r,mid+1,R,mk));}int qmx(int k,int l,int r,int L,int R,int mk){ if(l==L&&r==R)return t[k].mx+mk; int mid=l+r>>1;mk+=t[k].mk; if(R<=mid)return qmx(t[k].l,l,mid,L,R,mk); if(L>mid)return qmx(t[k].r,mid+1,r,L,R,mk); return max(qmx(t[k].l,l,mid,L,mid,mk),qmx(t[k].r,mid+1,r,mid+1,R,mk));}int main(){ int n=read(),i,j,ans,ls=0,q[4]; for(i=1;i<=n;++i)a[c[i]=i]=read(); sort(c+1,c+n+1,cmp); rt[1]=build(0,n); for(i=2;i<=n;++i)rt[i]=dec(rt[i-1],0,n,c[i-1]); for(i=read();i--;) { for(j=0;j<4;++j)q[j]=(read()+ls)%n+1;sort(q,q+4); for(int l=1,r=n,mid;l<=r;) { mid=l+r>>1; if(qmx(rt[mid],0,n,q[2],q[3],0) -qmn(rt[mid],0,n,q[0]-1,q[1]-1,0)<0)r=mid-1; else ans=mid,l=mid+1; } printf("%d\n",ls=a[c[ans]]); }}

 

转载于:https://www.cnblogs.com/ditoly/p/BZOJ2656.html

你可能感兴趣的文章
c# Mongodb两个字段不相等 MongoDB原生查询
查看>>
排序算法-冒泡排序
查看>>
finally 的作用是什么?
查看>>
嵌入式Linux的调试技术
查看>>
CSS3
查看>>
用友U9 基础使用文件所在目录
查看>>
iOS CALayer 学习(1)
查看>>
jquery 分页控件(一)
查看>>
StackAndQueue(栈与队列)
查看>>
URLOS安装、升级、卸载
查看>>
最新dedecms网页游戏开服表发号网站源码模板
查看>>
在win7下配置sql2005允许远程访问
查看>>
aspose.cell 设置excel里面的文字是超链接
查看>>
POJ 1067 取石子游戏
查看>>
django开发框架-view & template
查看>>
[Linux]systemd和sysV
查看>>
时间日期正则表达
查看>>
JSON.NET 简单的使用
查看>>
java 集合 HashMap
查看>>
三栏宽度自适应布局的三种方法及其优缺点
查看>>