【BZOJ2653】Middle(主席树)

题面

BZOJ

洛谷

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

题解

陈老师神题啊,丽洁姐最神啦

还是二分答案

区间内的中位数大于一个值?

将大于答案的数赋值为\(1\),小于的赋值\(-1\)

既然是左端点在\([a,b]\),右端点在\([c,d]\)

那么也就是\([b+1,c-1]\)必须选

而现在要中位数尽可能大

所以要选的就是\([a,b]\)的最大右子段和

\([c,d]\)的最大左子段和

而答案一定是某个数列中的数

排序之后依次把自己位置上的\(1\)变成\(-1\)即可

不可能开这么多线段树

显然是在主席树上直接修改

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 22222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Node
{
int lv,rv,sum;
int ls,rs,id;
}t[MAX<<6];
Node operator+(Node a,Node b)
{
Node c;
c.lv=max(a.lv,a.sum+b.lv);
c.rv=max(b.rv,b.sum+a.rv);
c.sum=a.sum+b.sum;
c.ls=a.id;c.rs=b.id;
return c;
}
int tot,rt[MAX];
void Build(int &x,int l,int r)
{
x=++tot;t[x].id=x;
if(l==r){t[x].lv=t[x].rv=t[x].sum=1;return;}
int mid=(l+r)>>1;
Build(t[x].ls,l,mid);Build(t[x].rs,mid+1,r);
t[x]=t[t[x].ls]+t[t[x].rs];t[x].id=x;
}
void Modify(int &x,int ff,int l,int r,int p,int w)
{
t[x=++tot]=t[ff];t[x].id=x;
if(l==r){t[x].lv=t[x].rv=t[x].sum=t[x].sum+w;return;}
int mid=(l+r)>>1;
if(p<=mid)Modify(t[x].ls,t[ff].ls,l,mid,p,w);
else Modify(t[x].rs,t[ff].rs,mid+1,r,p,w);
t[x]=t[t[x].ls]+t[t[x].rs];t[x].id=x;
}
Node Query(int x,int l,int r,int L,int R)
{
if(l==L&&r==R)return t[x];
int mid=(l+r)>>1;
if(R<=mid)return Query(t[x].ls,l,mid,L,R);
if(L>mid)return Query(t[x].rs,mid+1,r,L,R);
return Query(t[x].ls,l,mid,L,mid)+Query(t[x].rs,mid+1,r,mid+1,R);
}
int n,a[MAX],p[MAX];
bool cmp(int x,int y){return a[x]<a[y];}
int main()
{
n=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)p[i]=i;
Build(rt[1],1,n);
sort(&p[1],&p[n+1],cmp);
for(int i=1;i<=n;++i)
Modify(rt[i+1],rt[i],1,n,p[i],-2);
sort(&a[1],&a[n+1]);
int Q=read();
int ans=0,q[5];
while(Q--)
{
for(int i=1;i<=4;++i)q[i]=(read()+ans)%n+1;
sort(&q[1],&q[5]);
int l=1,r=n,Ans=1;
while(l<=r)
{
int mid=(l+r)>>1,ss=0;
if(q[2]+1<=q[3]-1)ss+=Query(rt[mid],1,n,q[2]+1,q[3]-1).sum;
ss+=Query(rt[mid],1,n,q[1],q[2]).rv;
ss+=Query(rt[mid],1,n,q[3],q[4]).lv;
if(ss>=0)Ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans=a[Ans]);
}
return 0;
}

【BZOJ2653】Middle(主席树)的更多相关文章

  1. [BZOJ2653]middle 主席树+二分

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

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

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

  3. Luogu2839 Middle 主席树、二分答案

    题目传送门:https://www.luogu.org/problemnew/show/P2839 题目大意:给出一个长度为$N$的序列与$Q$次询问,每次询问左端点在$[a,b]$,右端点在$[c, ...

  4. bzoj 2653 middle(主席树)

    题面:https://vjudge.net/problem/HYSBZ-2653 博客:https://blog.csdn.net/litble/article/details/78984846 这个 ...

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

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

  6. BZOJ 2653: middle [主席树 中位数]

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

  7. BZOJ 2653: middle 主席树 二分

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

  8. BZOJ 2653 middle | 主席树

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题解: 设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前an ...

  9. 洛谷P2839 [国家集训队]middle 主席树_二分

    Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...

随机推荐

  1. L014-第三关课前linux命令及基础知识考试手把手实战解答小节

    又是一周啊,以后保持一周一个微博吧. 这是一个堂解答考试题的课,那么就以题目来展开吧! 1.如何取得/etiantian文件的权限对应的数字内容,如-rw-r--r--为644,要求用命令获得644这 ...

  2. hive 空值、NULL判断

    hive中空值判断基本分两种 (1)NULL 与 \N hive在底层数据中如何保存和标识NULL,是由 alter table name SET SERDEPROPERTIES('serializa ...

  3. (转)python+opencv实现动态物体追踪

    原文链接:https://blog.csdn.net/cike14/article/details/50649811 import cv2 import numpy as np camera=cv2. ...

  4. MAC清理DS_Store和._文件

    打开终端输入 find . -name .DS_Store -type f -delete ; find . -type d | xargs dot_clean

  5. (python)剑指Offer 面试题51:数组中重复的数字

    问题描述 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1, ...

  6. POJ 3579 Median 二分加判断

    Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12453   Accepted: 4357 Descripti ...

  7. 算法笔记(c++)-使用递归函数逆序一个栈

    ---恢复内容开始--- 使用递归函数逆序一个栈 题目:使用递归函数,不借助其他数据结构逆序一个栈. 我的思路:使用递归函数保存栈中变量. 递归函数分两个,一个获取并移除栈底元素,另一个负责逆序.其实 ...

  8. 梯度下降算法以及其Python实现

    一.梯度下降算法理论知识 我们给出一组房子面积,卧室数目以及对应房价数据,如何从数据中找到房价y与面积x1和卧室数目x2的关系?   为了实现监督学习,我们选择采用自变量x1.x2的线性函数来评估因变 ...

  9. 处理了一个以前写的java小程序的异常

    之前用java做过0-99的数字和英文之间的翻译,输入数字就会翻译成英文,输入英文会翻译成数字,比如输入56  输出fiftysix   输入fiftysix  输出56, 发现这会有一个异常,当输入 ...

  10. 【leetcode】215. Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...