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 ...
随机推荐
- Oracle数据库之SQL基础和分支循环
一.SQL基础语言 DECLARE --声明 a ); --变量或对象 BEGIN a:='小明';-- := 表示给一个变量赋值 dbms_output.put_line(a); --输出用 dbm ...
- API的理解和使用——列表类型的命令
列表类型的命令及对应的时间复杂度 操作 命令 功能 时间复杂度 添加 rpush key value [value ...] 向右插入 O(k),k是元素个数 lpush key value [val ...
- elasticsearch 简单聚合查询示例
因为懒癌犯了,查询语句使用的截图而不是文字,导致了发布随笔的时候提示少于150字的随笔不能发布. 我就很郁闷了. 下面的查询都是前段时间工作中使用过的查询语句. 开始的时候是使用nodejs构建es查 ...
- (KEILv5)使用matlab绘制从KEIL memory导出的内存数据
使用matlab绘制从KEIL memory导出的内存数据 如标题,某些时候我们需要分析keil调试过程中的数据,比如从I2S.SPI.I2C或者UART获取到的波形数据,这些数据时数字流,通过逻辑分 ...
- iOS实时监控网络状态的改变
在网络应用中,有的时候需要对用户设备的网络状态进行实时监控,有两个目的: (1)让用户了解自己的网络状态,防止一些误会(比如怪应用无能) (2)根据用户的网络状态进行智能处理,节省用户流量,提高用户体 ...
- 蓝天白云大草原风景PSD背景素材
蓝天白云大草原风景PSD源文件背景素材,蓝天白云,大草原,风景,背景素材,自然风景,草原景色,绿色清新背景 地址:http://www.huiyi8.com/psd/
- bzoj 4066: 简单题 K-D树
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4066 题解 我们把每次的修改操作都当作二维平面上多了一个权值点 对于每组询问可以看做求一 ...
- /boot下面文件说明
config-3.10.0-229.el7.x86_64 <==此版本核心被编译时选择的功能与模组设定档 grub/ <==旧版 grub1 ,不需要理会这目录了! grub2/ < ...
- bzoj 4310 跳蚤 —— 后缀数组+二分答案+贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4310 二分答案——在本质不同的子串中二分答案! 如果二分到的子串位置是 st,考虑何时必须分 ...
- 洛谷P3372线段树模板1——线段树
题目:https://www.luogu.org/problemnew/show/P3372 线段树模板. 代码如下: #include<iostream> #include<cst ...