首先离散化,然后我们知道如果对于一个询问的区间[l1,r1],[l2,r2],我们二分到一个答案x,将[l1,r2]区间中的元素大于等于x的设为1,其余的设为-1,那么如果[l1,r1]的最大右区间和加上[r1,l2]的区间和加上[l2,r2]的最大左区间和大于等于0,那么最大的中位数一定大于等于x。因为这个区间中大于等于x的数量超过了一半,那么我们可以二分答案,然后判断最大的合法(见上文)区间和是否大于等于0。

  那么对于每个我们二分的值的区间-1,1情况我们不能建立n颗线段树,我们可以建立可持久化线段树来维护这个,最开始的初始值都为1,设rot[x]为二分的值为x的时候区间的1,-1情况的线段树,可以由rot[x-1]这颗线段树继承过来。

  反思:之前写的可持久化线段树都是建立的权值线段树,这次是用线段树维护区间值的,而且之前对于rot[x]只会有一次插入,这道题的rot[x]可能会有多次插入,在这里纠结了半天。还有我就是最后输出的是adr[ans],但是前面强制在线的时候我加的是ans,忘了改了= =。

/**************************************************************
Problem: 2653
User: BLADEVIL
Language: C++
Result: Accepted
Time:2012 ms
Memory:18196 kb
****************************************************************/ //By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 50010 using namespace std; struct rec {
int key,ans,num;
rec() {
key=ans=num=;
}
}a[maxn]; struct segment {
int left,right,maxr,maxl,sum;
int son[];
segment() {
left=right=maxr=maxl=sum=;
memset(son,,sizeof son);
}
}t[*maxn]; int n,m,tot;
int rot[maxn],adr[maxn]; bool cmp1(rec x,rec y) {
return x.ans<y.ans;
} bool cmp2(rec x,rec y) {
return x.num<y.num;
} void update(int x) {
t[x].sum=t[t[x].son[]].sum+t[t[x].son[]].sum;
t[x].maxl=max(t[t[x].son[]].sum+t[t[x].son[]].maxl,t[t[x].son[]].maxl);
t[x].maxr=max(t[t[x].son[]].sum+t[t[x].son[]].maxr,t[t[x].son[]].maxr);
} void build(int &x,int l,int r) {
if (!x) x=++tot;
t[x].left=l; t[x].right=r;
if (l==r) {
t[x].sum=t[x].maxl=t[x].maxr=;
return ;
}
int mid=t[x].left+t[x].right>>;
build(t[x].son[],l,mid); build(t[x].son[],mid+,r);
update(x);
} void insert(int &x,int rot,int y) {
if (!x) x=++tot;
t[x].left=t[rot].left; t[x].right=t[rot].right;
if (t[x].left==t[x].right) {
t[x].sum=t[x].maxl=t[x].maxr=-;
return ;
}
int mid=t[x].left+t[x].right>>;
if (y>mid) {
if (!t[x].son[]) t[x].son[]=t[rot].son[];
if (t[x].son[]==t[rot].son[]) t[x].son[]=;
insert(t[x].son[],t[rot].son[],y);
} else {
if (!t[x].son[]) t[x].son[]=t[rot].son[];
if (t[x].son[]==t[rot].son[]) t[x].son[]=;
insert(t[x].son[],t[rot].son[],y);
}
update(x);
} segment combine(segment x,segment y) {
segment ans;
ans.sum=x.sum+y.sum;
ans.maxl=max(x.sum+y.maxl,x.maxl);
ans.maxr=max(y.sum+x.maxr,y.maxr);
return ans;
} segment query(int x,int l,int r) {
if ((t[x].left==l)&&(t[x].right==r)) return t[x];
int mid=t[x].left+t[x].right>>;
if (l>mid) return query(t[x].son[],l,r); else
if (r<=mid) return query(t[x].son[],l,r); else
return combine(query(t[x].son[],l,mid),query(t[x].son[],mid+,r));
} int main(){
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[a[i].num=i].ans);
sort(a+,a++n,cmp1);
int sum=,cur=a[].ans; adr[]=a[].ans;
for (int i=;i<=n;i++) if (a[i].ans==cur) a[i].key=sum; else a[i].key=++sum,adr[sum]=cur=a[i].ans;
//sort(a+1,a+1+n,cmp2);
//for (int i=1;i<=n;i++) printf("%d ",a[i].key); printf("\n");
build(rot[],,n);
for (int i=;i<=n;i++) insert(rot[a[i].key],rot[a[i].key-],a[i].num);
//for (int i=1;i<=tot;i++) printf("%d %d %d %d %d %d %d\n",i,t[i].left,t[i].right,t[i].son[0],t[i].son[1],t[i].maxl,t[i].maxr);
//for (int i=1;i<=n;i++) printf("%d ",adr[i]); printf("\n");
scanf("%d",&m);
int ans=;
while (m--) {
int ask[]; for (int i=;i<=;i++) scanf("%d",&ask[i]);
for (int i=;i<=;i++) ask[i]=(ask[i]+adr[ans])%n+;
ans=;
sort(ask+,ask+);
int l=,r=n;
while (l<=r) {
int mid=l+r>>,TOT=;
//printf("%d %d %d\n",l,r,a[mid].key);
//printf("%d %d\n",l,r);
segment a1=query(rot[a[mid].key-],ask[],ask[]),a2=query(rot[a[mid].key-],ask[],ask[]);
if (ask[]+<=ask[]-) TOT=query(rot[a[mid].key-],ask[]+,ask[]-).sum;
//printf("%d\n",TOT);
TOT+=a1.maxr+a2.maxl; //printf("%d\n",TOT);
//printf("%d\n",a1.maxr);
if (TOT>=) ans=a[mid].key,l=mid+; else r=mid-;
}
printf("%d\n",adr[ans]);
}
return ;
}

bzoj 2653 二分答案+可持久化线段树的更多相关文章

  1. BZOJ2653middle——二分答案+可持久化线段树

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

  2. BZOJ 2653 middle 二分答案+可持久化线段树

    题目大意:有一个序列,包含多次询问.询问区间左右端点在规定区间里移动所得到的最大中位数的值. 考虑对于每个询问,如何得到最优区间?枚举显然是超时的,只能考虑二分. 中位数的定义是在一个序列中,比中位数 ...

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

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

  4. BZOJ 3542 [Poi2014]Couriers ——可持久化线段树

    [题目分析] 查找区间内出现次数大于一半的数字. 直接用主席树,线段树上维护区间大小,由于要求出现次数大于一半,每到一个节点可以分治下去. 时间复杂度(N+Q)logN [代码] #include & ...

  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. BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)

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

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

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

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

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

随机推荐

  1. vbs习题

    练习题: 1.输入3个数,输出其中最大的那个值. Option Explicit Dim intA,intB,intC intA=CInt(InputBox("请输入a:")) i ...

  2. XHTML5 与 HTML 4.01的差异

    在 HTML 4.01 中,td 元素的 "bgcolor"."height"."width" 以及 "nowrap" ...

  3. 使用ResourceBundle 类读取 src 下的 xxx.properties 文件

    之前要读取 src 下的 .properties 文件都是使用的类加载器,加载类路径下的资源文件当做一个流来处理,load 到一个 Properties 对象上. jdbc.properties 代码 ...

  4. Android Studio 修改 包名

    Android Studio上修改项目(module)的包名(Package Name)   当你对着包名右击,查找Refactor(重构)下的Rename(快捷键:SHIFT+F6)时,弹出来的仅仅 ...

  5. 【.Net】输出的字符靠右对齐

    先看下面的这组字符,如果输出来,它是无法靠右对齐: " }; foreach (string s in s1) { string s2 = s; Console.WriteLine(s2); ...

  6. FZU2127_养鸡场

    题目的意思为要你求出满足三边范围条件且周长为n的三角形的数目. 其实做法是直接枚举最短边,然后就可以知道第二条边的取值范围,同时根据给定的范围缩小范围. 同时根据第二条边的范围推出第三条边的范围,再次 ...

  7. 命令行下django-admin.py参数不起作用的问题解决

    django官方turial中创建本地web站点时,使用如下命令 django-admin.py startproject mysite 说一下我在使用时碰到的几个问题: 1.无法找到django-a ...

  8. C++11新利器

    C++11常用特性的使用经验总结 unordered_map可能用的会比较多 省的写哈希表了. 但是浪费空间

  9. git 删除远程仓库的命令

    # 删除远程仓库的命令: git branch -r -d origin/branch-name #其中这条命令必须执行,远程仓库才会删除 git push origin :branch-name # ...

  10. ubuntu 安装部分设置U盘启动系统安装盘操作

    https://jingyan.baidu.com/article/6079ad0ec4925728ff86db02.html 第三种方法适合新机型,在启动时按F10或F11,可直接选择启动模式 -- ...