BZOJ2653 middle(二分答案+主席树)
与中位数有关的题二分答案是很常用的trick。二分答案之后,将所有大于它的看成1小于它的看成-1,那么只需要判断是否存在满足要求的一段和不小于0。
由于每个位置是1还是-1并不固定,似乎不是很好算。考虑暴力一点的想法:对于每一种答案预处理。这样查询就很好办了,线段树上每个区间维护最大前缀和后缀和及总和即可。并且可以发现按答案从小到大考虑的话每个位置都是开始一段为1之后为-1,总修改次数只有n次,建主席树即可。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 20010
int n,m,a[N],b[N],root[N],lastans,cnt=;
vector<int> p[N];
struct data{int l,r,sum,pre,suf;
}tree[N<<];
void build(int &k,int l,int r)
{
k=++cnt;tree[k].sum=tree[k].pre=tree[k].suf=r-l+;
if (l==r) return;
int mid=l+r>>;
build(tree[k].l,l,mid);
build(tree[k].r,mid+,r);
}
void modify(int &k,int l,int r,int x)
{
tree[++cnt]=tree[k];k=cnt;
tree[k].sum-=;
if (l==r) {tree[k].pre=tree[k].suf=-;return;}
int mid=l+r>>;
if (x<=mid) modify(tree[k].l,l,mid,x);
else modify(tree[k].r,mid+,r,x);
tree[k].pre=max(tree[tree[k].l].pre,tree[tree[k].l].sum+tree[tree[k].r].pre);
tree[k].suf=max(tree[tree[k].r].suf,tree[tree[k].r].sum+tree[tree[k].l].suf);
}
int querysum(int k,int l,int r,int x,int y)
{
if (x>y) return ;
if (l==x&&r==y) return tree[k].sum;
int mid=l+r>>;
if (y<=mid) return querysum(tree[k].l,l,mid,x,y);
else if (x>mid) return querysum(tree[k].r,mid+,r,x,y);
else return querysum(tree[k].l,l,mid,x,mid)+querysum(tree[k].r,mid+,r,mid+,y);
}
int querypre(int k,int l,int r,int x,int y)
{
if (l==x&&r==y) return tree[k].pre;
int mid=l+r>>;
if (y<=mid) return querypre(tree[k].l,l,mid,x,y);
else if (x>mid) return querypre(tree[k].r,mid+,r,x,y);
else return max(querypre(tree[k].l,l,mid,x,mid),querysum(tree[k].l,l,mid,x,mid)+querypre(tree[k].r,mid+,r,mid+,y));
}
int querysuf(int k,int l,int r,int x,int y)
{
if (l==x&&r==y) return tree[k].suf;
int mid=l+r>>;
if (y<=mid) return querysuf(tree[k].l,l,mid,x,y);
else if (x>mid) return querysuf(tree[k].r,mid+,r,x,y);
else return max(querysuf(tree[k].r,mid+,r,mid+,y),querysum(tree[k].r,mid+,r,mid+,y)+querysuf(tree[k].l,l,mid,x,mid));
}
int calc(int k,int a,int b,int c,int d)
{
return querysum(root[k],,n,b+,c-)+querysuf(root[k],,n,a,b)+querypre(root[k],,n,c,d);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj2653.in","r",stdin);
freopen("bzoj2653.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++) b[i]=a[i]=read();
sort(b+,b+n+);
int t=unique(b+,b+n+)-b;
for (int i=;i<=n;i++)
{
a[i]=lower_bound(b+,b+t,a[i])-b;
p[a[i]].push_back(i);
}
build(root[],,n);
for (int i=;i<t;i++)
{
root[i]=root[i-];
for (int j=;j<p[i-].size();j++)
modify(root[i],,n,p[i-][j]);
}
m=read();
while (m--)
{
int q[]={(read()+lastans)%n,(read()+lastans)%n,(read()+lastans)%n,(read()+lastans)%n};
sort(q,q+);
int l=,r=t-,ans=;
while (l<=r)
{
int mid=l+r>>;
if (calc(mid,q[]+,q[]+,q[]+,q[]+)>=) ans=mid,l=mid+;
else r=mid-;
}
printf("%d\n",lastans=b[ans]);
}
return ;
}
BZOJ2653 middle(二分答案+主席树)的更多相关文章
- bzoj 2653 middle 二分答案 主席树判定
判断中位数是否可行需要将当前的解作为分界,大于其的置为1,小于为-1,然后b-c必选,ab,cd可不选,这个用线段树判定就好 但不能每次跑,所以套主席树,按权值排序,构建主席树,更新时将上一个节点改为 ...
- BZOJ5343: [Ctsc2018]混合果汁 二分答案+主席树
分析: 整体二分或二分答案+主席树,反正没有要求强制在线,两个都可以做... 贪心还是比较显然的,那么就是找前K大的和...和CQOI的任务查询系统很像 附上代码: #include <cstd ...
- BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树
BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树 题意:给出每个果汁的价格p,美味度d,最多能放的体积l.定义果汁混合后的美味度为果汁的美味度的最小值. m次询问,要求花费不大于g, ...
- 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)
K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...
- BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...
- BZOJ1926[Sdoi2010]粟粟的书架——二分答案+主席树
题目描述 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位 ...
- Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)
链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...
- BZOJ 4556: [Tjoi2016&Heoi2016]字符串(后缀数组 + 二分答案 + 主席树 + ST表 or 后缀数组 + 暴力)
题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s ...
- BZOJ3277 串(后缀数组+二分答案+主席树)
因为不会SAM,考虑SA.将所有串连起来并加分隔符,每次考虑计算以某个位置开始的子串有多少个合法. 对此首先二分答案,找到名次数组上的一个区间,那么只需要统计有多少个所给串在该区间内出现就可以了.这是 ...
随机推荐
- Android 连续按两次back键退出系统
需求:在程序的首页,连续按两次back键退出Androd程序. 第一步:新建一个GApplication类继承Application,在GApplication中添加一个用于存放Activity的集合 ...
- P2731 骑马修栅栏 Riding the Fences
题目描述 John是一个与其他农民一样懒的人.他讨厌骑马,因此从来不两次经过一个栅栏.你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次.John能从任何一个顶 ...
- vi 替换
在vi编辑器中,能够利用 :s命令能够实现字符串的替换.详细的使用方法例如以下: 1.:s/str1/str2/ 用字符串 str2 替换行中首次出现的字符串str1: 2.:s/str1/str2/ ...
- Codeforces 954C Matrix Walk (思维)
题目链接:Matrix Walk 题意:设有一个N×M的矩阵,矩阵每个格子都有从1-n×m的一个特定的数,具体数的排列如图所示.假设一个人每次只能在这个矩阵上的四个方向移动一格(上下左右),给出一条移 ...
- mysql基础(二)—— 简单sql
查询 select * from company select c.code from company c; select m.bookname from myview m; (myview为视图) ...
- 在git与tortoisegit中使用openSSH与PuTTY
问题 在使用Git与tortoisegit的时候,指定远程版本库的地址有2种方式: 使用https方式的git地址非常直接(https://xxx.oschina.net/xxx.git),基本上什么 ...
- 【Tableau】电商广告投放的地域分析
分析师的职责是利用处理数据获取信息,提炼规律,帮助企业正确决策业务方向. 所以,一个好的分析师绝不能被数据所困,既要深入业务,理解业务,也要高瞻远瞩,以领导者的思维借助数据分析的辅助做出判断. [结构 ...
- Ubuntu 开机自动启动
# 开机启动 2018-12-13在etc目录下建立loraserver.sh文件,[**注意**:设置脚本的运行属性]其内容为 #!/bin/bash cd /home/zqkj/loraserve ...
- Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果
Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果 梗概: 一. 摄像机围绕目标物体旋转, 即摄像机离目标物体有一定的距离且旋转轴心为该物体的位置. 二. 当目标物体被障碍物挡住后, 需要将摄像机 ...
- (1) English Learning
1. no-brainer 不必花脑筋的事物 This tool is really no-brainer that almost everyone can use it. 这个工具太简单用了,不会 ...