【BZOJ2653】middle 二分+可持久化线段树
【BZOJ2653】middle
Description
Input
Output
Q行依次给出询问的答案。
Sample Input
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 二分+可持久化线段树的更多相关文章
- BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)
换markdown写了.. 题意: 给你一个1e5的字符串,1e5组询问,求\([l_1,r_1]\)的所有子串与\([l_2,r_2]\)的lcp 思路: 首先可以发现答案是具有单调性的,我们考虑二 ...
- 【XSY2720】区间第k小 整体二分 可持久化线段树
题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...
- bzoj 2653 middle (可持久化线段树)
middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1981 Solved: 1097[Submit][Status][Discuss] D ...
- 【BZOJ-2653】middle 可持久化线段树 + 二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1298 Solved: 734[Submit][Status][Discu ...
- [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\),判断序列和是否非负. 对于询问\(( ...
- 【bzoj2653】middle 可持久化线段树区间合并
题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...
- 洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)
有点类似NOI2014购票 首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$ 这个显然是可以斜率优化的... $\frac {f(j)-f(k)}{dep_j ...
- 计蒜客 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 ...
随机推荐
- AnjularJS小项目,小案例,练手,猜数字
之前自己就学了点AnjularJS,都是在菜鸟教程里面将基础的只是大致过了一遍,没怎么自己动手做什么东西练练手,但还是觉得纸上得来终觉浅,得知此事要躬行啊,今天就做了个猜数字的小游戏,觉得效果还不错, ...
- C# 调用bat文件
引入名称空间: using System.Diagnostics; Process proc = null; try { string targetDir = string.Format(@" ...
- selenium2.0 --常用函数2
新建实例driver = webdriver.Chrome() 1.获取当前页面的Url函数 方法:current_url 实例: driver.current_url 2.获取元素坐标 方法:loc ...
- Hive SQL 常见问题(转载)
http://www.aboutyun.com/thread-14942-1-1.html 问题导读 1.Hive查询语句和SQL查询语句区别与联系. 2.distribute by.group by ...
- JAVA Socket 底层是怎样基于TCP/IP 实现的???
首先必须明确:TCP/IP模型中有四层结构: 应用层(Application Layer).传输层(Transport Layer).网络层(Internet Layer ).链路层( ...
- deepin linux 15.3安装完eclipse启动报错An error has occurred.
原因是系统中安装了jdk9 导致的. 卸载jdk9就可以了 $ java -version Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings ...
- Github上Fork代码,及源码修改
iOS开发中经常遇到这种情况,你使用的第三方库不能完全满足自己项目需要,只能修改源码来解决. 我们以前的解决办法是,添加到项目中直接修改源码.这样就有一个问题,不能和源库同步,当作者更新后你不能(po ...
- spoj7001 Visible Lattice Points 莫比乌斯反演+三维空间互质对数
/** 题目:Visible Lattice Points 链接:https://vjudge.net/contest/178455#problem/A 题意:一个n*n*n大小的三维空间.一侧为(0 ...
- codeforces 825F F. String Compression dp+kmp找字符串的最小循环节
/** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: d ...
- PHP 表格 post 提交 接受
<form action="<?php echo site_url('home/order/sned_order'); ?>" method="post ...