duliu——思维+线段树
题目
【题目描述】
小 `D` 喜欢出毒瘤题毒人。当然,他的毒瘤更多体现在若干个难题组合在同一场比赛时。
小 `D` 脑中有 $n$ 个毒瘤题 idea,第 $i$ 个的毒值为$d_i$。当第 $i$ 个题和第 $j$ 个题同时出现在一场比赛中,会产生$f(i,j) = d_i + d_j$ 的毒性。
小 `D` 决定用这些题在 YLOJ 上办 $m$ 场在线比赛。
• 由于这个 OJ 还在~~咕咕~~开发,`YLOJ Extremelyhard Round #i` 选取的题目编号集合只能为 $[l_i,r_i]$ 的一个非空子区间 $[a_i,b_i]$。
• 因为这个 round 是 extremelyhard 的,所以需要满足$\sum\limits_{a_i \le j,k \le b_i} f(j,k) \ge x_i$。
• 不过,为了防止题目过分毒瘤而被喷,小 `D` 希望最小化$max_{a_i \le j \le b_i} \{d_i\}$,而你需要告诉他这个最小值。
【输入格式】
从文件 `duliu.in` 中读入数据。
第一行,正整数$n$,自然数$m$。
第二行,$n$ 个正整数,第 $i$ 个元素代表$d_i$。
接下来 $m$ 行,每行三个正整数,分别代表$l_i、r_i、x_i$。
【输出格式】
输出到文件 `duliu.out` 中。
输出 $m$ 行,每行一个整数,代表$min\{max_{a_i \le j \le b_i}\{d_j\}\}$,若没有合法区间,则输出$-1$。
【样例输入一】
5 2
1 1 2 3 4
1 5 2
1 5 11
【样例输出一】
1
2
【样例输入二】
5 4
1 3 2 4 6
1 3 3
1 3 2
2 4 10
1 1 1556528051
【样例输出二】
2
1
3
-1
【数据范围与提示】
保证,$n,m \le 3 \times 10^5,d_i \le 10^7,1 \le l_i \le r_i \le n,x_i \le 10^{18}$。
题解
毒瘤题目,区间价值和是 $ w=sum*len*2 $,而不是 $ sum*len $,$ j $ 不小于 $ k $
对于以 $ l $ 为起点和以 $ r $ 为结尾的区间,可以直接二分+ RMQ 解决
对于在中间的区间,显然是一个三维偏序,可以整体二分解决
然而本题卡常
记中间的区间为 $ [l_i,r_i] $,和为 $ w_i $
可以发现,当 $ r_i>r $ 时,答案显然没有以 $ r $ 为结尾的区间优,于是就转化为二维偏序,求满足 $ l_i \geq L,w_i \geq x_i $ 的区间中最大值最小
对于一个 $ a_i $,可以预处理出最大值为 $ a_i $ 的区间及它的 $ w_i $
将询问按 $ x_i $,区间按 $ w_i $ 从大到小排序,满足 $ w_i>=x_i $
将 $ a_i $ 记录到以位置为下标的线段树的 $ l_i $ 上,查询的时候只要查询 $ [L,P_r] $ 的最小值即可($ P_r $ 为以 $ r $ 为结尾的区间的左端点)
时间效率:$ O(n \log n) $
代码
#include<bits/stdc++.h>
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
LL R(){
LL x;bool f=;char ch;_(!)if(ch=='-')f=;x=ch^;
_()x=(x<<)+(x<<)+(ch^);return f?x:-x;}
const int N=3e5+;
int n,m,a[N],st[N][],lg,tr[N<<],tot,ans[N];
LL sum[N];
struct node{int x,id;}s[N];
struct pig{int l,r,x;LL w;}p[N],q[N];
bool cmp(node a,node b){return a.x>b.x;}
bool cmp2(pig a,pig b){return a.w>b.w;}
set<int> h;
set<int>::iterator it;
#define ls rt<<1
#define rs rt<<1|1
void update(int rt,int l,int r,int x,int v){
if(l==r){tr[rt]=min(tr[rt],v);return;}
int mid=(l+r)>>;
if(x<=mid)update(ls,l,mid,x,v);
else update(rs,mid+,r,x,v);
tr[rt]=min(tr[ls],tr[rs]);
return;
}
int query(int rt,int l,int r,int ql,int qr){
if(ql<=l&&qr>=r)return tr[rt];
int mid=(l+r)>>,ans=1e9;
if(ql<=mid)ans=query(ls,l,mid,ql,qr);
if(qr>mid)ans=min(ans,query(rs,mid+,r,ql,qr));
return ans;
}
int rmq(int l,int r){
int x=log2(r-l+);
return max(st[l][x],st[r-(<<x)+][x]);
}
int main(){
n=R(),m=R(),lg=log2(n)+;
for(int i=;i<=n;i++)
sum[i]=(st[i][]=a[i]=R())+sum[i-],s[i]=(node){a[i],i};
sort(s+,s++n,cmp);
h.insert(),h.insert(n+);
for(int i=,l,r;i<=n;i++){
it=h.lower_bound(s[i].id);
r=*it-,it--,l=*it+;
p[i]=(pig){l,r,s[i].x,(sum[r]-sum[l-])*(r-l+)*};
h.insert(s[i].id);
}
for(int i=;i<=m;i++){
int l=R(),r=R();LL w=R();
if((sum[r]-sum[l-])*(r-l+)*<w)ans[i]=-;
else q[++tot]=(pig){l,r,i,w};
}
sort(p+,p++n,cmp2),sort(q+,q++tot,cmp2);
memset(tr,0x3f,sizeof tr);
for(int i=;i<=lg;i++)
for(int j=;j+(<<i)-<=n;j++)
st[j][i]=max(st[j][i-],st[j+(<<(i-))][i-]);
for(int i=,j=;i<=tot;i++){
int l=q[i].l,r=q[i].r,res=;
while(l<=r){
int mid=(l+r)>>;
if((sum[mid]-sum[q[i].l-])*(mid-q[i].l+)*<q[i].w) l=mid+;
else r=mid-,res=mid;
}
ans[q[i].x]=rmq(q[i].l,res);
l=q[i].l,r=q[i].r,res=;
while(l<=r){
int mid=l+r>>;
if((sum[q[i].r]-sum[mid-])*(q[i].r-mid+)*<q[i].w) r=mid-;
else l=mid+,res=mid;
}
ans[q[i].x]=min(ans[q[i].x],rmq(res,q[i].r));
while(j<=n&&p[j].w>q[i].w) update(,,n,p[j].l,p[j].x),j++;
ans[q[i].x]=min(ans[q[i].x],query(,,n,q[i].l,res));
}
for(int i=;i<=m;i++)printf("%d\n",ans[i]);
return ;
}
duliu——思维+线段树的更多相关文章
- Buy Tickets POJ - 2828 思维+线段树
Buy Tickets POJ - 2828 思维+线段树 题意 是说有n个人买票,但是呢这n个人都会去插队,问最后的队列是什么情况.插队的输入是两个数,第一个是前面有多少人,第二个是这个人的编号,最 ...
- 牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)
前言 听说是线段树离线查询?? 做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线.在线操作. 这题赛后看代码发现有人用的树状数组,$tql$.当然能用树状数组写的线段树也 ...
- MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思维+线段树维护hash值
F - Permutation 思路:对于当前的值x, 只需要知道x + k, x - k这两个值是否出现在其左右两侧,又因为每个值只有一个, 所以可以转换成,x+k, x-k在到x所在位置的时候是否 ...
- 51nod 1272 思维/线段树
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1272 1272 最大距离 题目来源: Codility 基准时间限制:1 ...
- Codeforces 755D:PolandBall and Polygon(思维+线段树)
http://codeforces.com/problemset/problem/755/D 题意:给出一个n正多边形,还有k,一开始从1出发,向第 1 + k 个点连一条边,然后以此类推,直到走完 ...
- codeforces 459 D. Pashmak and Parmida's problem(思维+线段树)
题目链接:http://codeforces.com/contest/459/problem/D 题意:给出数组a,定义f(l,r,x)为a[]的下标l到r之间,等于x的元素数.i和j符合f(1,i, ...
- p3792 由乃与大母神原型和偶像崇拜(思维+线段树)
要求 1.修改x位置的值为y 2.查询区间l,r是否可以重排为值域上连续的一段 可以,很lxl 然后一开始思考合并区间,但是发现可以重排序,GG 然后想了特殊性质,比如求和,但是显然可以被叉 这时候我 ...
- CSU 1809 Parenthesis 思维+线段树
1809: Parenthesis Submit Page Summary Time Limit: 5 Sec Memory Limit: 128 Mb Submitte ...
- 并查集&线段树&树状数组&排序二叉树
超级无敌巨牛逼并查集(带权并查集)https://vjudge.net/problem/UVALive-4487 带删点的加权并查集 https://vjudge.net/problem/UVA-11 ...
随机推荐
- 服务器安装tensorflow导入模块报错Illegal instruction (core dumped)
在ubuntu上安装tensorflow后导入模块显示Illegal instruction (core dumped) 服务器的版本是Ubuntu 16.04.5 降低版本,成功导入模块 pip3 ...
- elasticsearch 简单聚合查询示例
因为懒癌犯了,查询语句使用的截图而不是文字,导致了发布随笔的时候提示少于150字的随笔不能发布. 我就很郁闷了. 下面的查询都是前段时间工作中使用过的查询语句. 开始的时候是使用nodejs构建es查 ...
- 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】
本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...
- idea创建maven-archetype-webapp项目无java目录
使用idea创建一个maven-archetype-webapp项目 查看项目的目录结构,在main的目录下没有java目录 在main目录下创建java目录 使用快捷键 ctrl+alt+shift ...
- codeforces 659E E. New Reform(图论)
题目链接: E. New Reform time limit per test 1 second memory limit per test 256 megabytes input standard ...
- OpenCV——PS 滤镜算法之平面坐标到极坐标的变换
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...
- composer镜像安装laravel
博主最近在学习Laravel的框架的相关知识,对于Laravel的许多新特性,大家最好还是去查看官网文档最好,Laravel的文档非常完善,中文英文的都有,可以很好的解决你的困惑. 但是我们会发现学习 ...
- django-crontab 定时执行任务方法
需求 每天请求一封邮件,并读取该邮件 这个其实可以使用linux 自带了crontab实现,但是毕竟是django 开发.想着不知道有没有方法可以从django 中实现. 简单搜索了下,这方面的方法确 ...
- python+selenium自动化测试环境搭建
selenium 是一个web的自动化测试工具,不少学习功能自动化的同学开始首选selenium ,相因为它相比QTP有诸多有点: * 免费,也不用再为破解QTP而大伤脑筋 * 小巧,对于不同的语 ...
- Digging-贪心
When it comes to the Maya Civilization, we can quickly remind of a term called the end of the world. ...