bzoj 2653 二分答案+可持久化线段树
首先离散化,然后我们知道如果对于一个询问的区间[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 二分答案+可持久化线段树的更多相关文章
- BZOJ2653middle——二分答案+可持久化线段树
题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在 ...
- BZOJ 2653 middle 二分答案+可持久化线段树
题目大意:有一个序列,包含多次询问.询问区间左右端点在规定区间里移动所得到的最大中位数的值. 考虑对于每个询问,如何得到最优区间?枚举显然是超时的,只能考虑二分. 中位数的定义是在一个序列中,比中位数 ...
- bzoj 2653 middle (可持久化线段树)
middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1981 Solved: 1097[Submit][Status][Discuss] D ...
- BZOJ 3542 [Poi2014]Couriers ——可持久化线段树
[题目分析] 查找区间内出现次数大于一半的数字. 直接用主席树,线段树上维护区间大小,由于要求出现次数大于一半,每到一个节点可以分治下去. 时间复杂度(N+Q)logN [代码] #include & ...
- [BZOJ 2653] middle(可持久化线段树+二分答案)
[BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...
- BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)
BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...
- BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)
换markdown写了.. 题意: 给你一个1e5的字符串,1e5组询问,求\([l_1,r_1]\)的所有子串与\([l_2,r_2]\)的lcp 思路: 首先可以发现答案是具有单调性的,我们考虑二 ...
- BZOJ 2653 middle (可持久化线段树+中位数+线段树维护最大子序和)
题意: 左端点在[a,b],右端点在[c,d],求这个线段里中位数(上取整)最大值 思路: 对数组离散化,对每一个值建中位数的可持久化线段树(有重复也没事),就是对于root[i],大于等于i的值为1 ...
- 【BZOJ-2653】middle 可持久化线段树 + 二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1298 Solved: 734[Submit][Status][Discu ...
随机推荐
- Dbgrid控件多重选择的怪问题。BookMarkList,BookMark,使用书签,用的ADOQuery控件。100分送上,急阿!!!请高手帮忙!
Dbgrid控件多重选择的怪问题.BookMarkList,BookMark,使用书签,用的ADOQuery控件.100分送上,急阿!!!请高手帮忙! ( 积分: 100 )<br />p ...
- 第204天:js---重载和多态
一.根据arguments个数实现重载 js本身不支持重载,所以只能通过其他方式实现,arguments检测传参的个数,然后再执行不同的方式 function add() { var sum = 0 ...
- 第91天:CSS3 属性选择器、伪类选择器和伪元素选择器
一.属性选择器 其特点是通过属性来选择元素,具体有以下5种形式: 1.E[attr] 表示存在attr属性即可: div[class] 2.E[attr=val] 表示属性值完全等于val: ...
- 第73天:jQuery基本动画总结
一.DOM对象跟jQuery对象相互转换 jQuery对象转换成DOM对象: 方式一:$(“#btn”)[0] 方式二:$(“#btn”).get(0) DOM对象转换成jQuery对象: $(doc ...
- .net下使用NPOI读取Excel表数据
这里只写MVC下的情况 public ActionResult Index() { var path = Server.MapPath(@"/content/user.xlsx") ...
- 【bzoj4428】[Nwerc2015]Debugging调试 数论+记忆化搜索
题目描述 一个 $n$ 行的代码出了bug,每行都可能会产生这个bug.你要通过输出调试,在其中加入printf来判断bug出现的位置.运行一次程序的时间为 $r$ ,加入一条printf的时间为 $ ...
- BZOJ4939 Ynoi2016掉进兔子洞(莫队+bitset)
容易发现要求三个区间各数出现次数的最小值.考虑bitset,不去重离散化后and一发就可以了.于是莫队求出每个区间的bitset.注意空间开不下,做多次即可.输出的东西错了都能调一年服了我了. #in ...
- Tajo--一个分布式数据仓库系统(设计架构)
上一篇Tajo--一个分布式数据仓库系统(概述)废话了一通,下面介绍一下Tajo的体系结构.以及官方的实验成果吧 一.体系架构 Tajo采用了Master-Worker架构(下图虚线框目前还在计划中) ...
- 【BZOJ1416/1498】【NOI2006】神奇的口袋(数论,概率)
[BZOJ1416/1498][NOI2006]神奇的口袋(数论,概率) 题面 BZOJ1416 BZOJ1498 洛谷 题面都是图片形式是什么鬼.. 题解 考虑以下性质 1.\(x[1],x[2]. ...
- LINUX内核分析第四周——扒开系统调用的三层皮
LINUX内核分析第四周--扒开系统调用的三层皮 李雪琦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...