区间的价值

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 662    Accepted Submission(s): 329

Problem Description
我们定义“区间的价值”为一段区间的最大值*最小值。

一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)。

现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。

当然,由于这个问题过于简单。

我们肯定得加强一下。

我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。

样例解释:

长度为1的最优区间为2−2 答案为6∗6

长度为2的最优区间为4−5 答案为4∗4

长度为3的最优区间为2−4 答案为2∗6

长度为4的最优区间为2−5 答案为2∗6

长度为5的最优区间为1−5 答案为1∗6

 
Input
多组测试数据

第一行一个数n(1≤n≤100000)。

第二行n个正整数(1≤ai≤109),下标从1开始。

由于某种不可抗力,ai的值将会是1∼109内<b style="color:red;">随机产生</b>的一个数。(除了样例)

 
Output
输出共n行,第i行表示区间长度为i的区间中最大的区间价值。
 
Sample Input
5
1 6 2 4 4
 
Sample Output
36
16
12
12
6
 
Source
 
首先回顾一下快排的思想:快排每次划分,都是从随机找一个值作为阀值(简单起见,通常找第一个),然后从需要划分的区间的最右端找比阀值小的值,用这个值去填最左端那个位置,从最左端找比阀值大的值,用这个值填最右端那个位置,交替去找,知道low和high相等,然后将阀值放到该位置,这次划分结束,阀值左边的值都比阀值右边的值要小。递归排序阀值左边的区间和右边的区间,最终保证有序。
这个题目要求的是区间长度为i的区间中最小值和最大值的乘积的最大值。我们拿到一段区间l, r,假设这段区间中的最小值的位置为idmin,最大值的位置为idmax,这段区间中的所有区间长度大于等于abs(idmin-idmax)+1的区间都可以被a[idmin]*a[idmax]更新到,由于我们要的是最大值,所以我们以最小值为分隔,递归求解左部分和右部分,都不能包含分隔。
 
 
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
using namespace std;
typedef long long LL;
#define mid (L+R)/2
#define lson rt*2,L,mid
#define rson rt*2+1,mid+1,R
#pragma comment(linker, "/STACK:102400000,102400000")
const int maxn = 1e5+300;
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef unsigned long long ULL;
struct Seg{
LL val, Min, Max;
int idmin, idmax;
}segs[maxn*4];
LL a[maxn];
LL ans[maxn];
int n;
void PushUP(int rt){
segs[rt].Max = max(segs[rt*2].Max,segs[rt*2+1].Max);
segs[rt].Min = min(segs[rt*2].Min,segs[rt*2+1].Min);
if(segs[rt*2].Max > segs[rt*2+1].Max)
segs[rt].idmax = segs[rt*2].idmax;
else segs[rt].idmax = segs[rt*2+1].idmax;
if(segs[rt*2].Min < segs[rt*2+1].Min)
segs[rt].idmin = segs[rt*2].idmin;
else segs[rt].idmin = segs[rt*2+1].idmin;
}
void buildtree(int rt,int L,int R){
if(L == R){
segs[rt].val = a[L];
segs[rt].idmax = segs[rt].idmin = L;
segs[rt].Min = segs[rt].Max = a[L];
return;
}
buildtree(lson);
buildtree(rson);
PushUP(rt);
}
int querymin(int rt,int L,int R,int l_ran,int r_ran){
if(l_ran<=L&&R<=r_ran){
return segs[rt].idmin;
}
int id = 0;
if(l_ran <= mid){
id = querymin(lson,l_ran,r_ran);
}
if(r_ran > mid){
int tid = querymin(rson,l_ran,r_ran);
if(id != 0){
if(a[id] > a[tid])
id = tid;
}else{
id = tid;
}
}
return id;
}
int querymax(int rt,int L,int R,int l_ran,int r_ran){
if(l_ran<=L&&R<=r_ran){
return segs[rt].idmax;
}
int id = 0;
if(l_ran <= mid){
id = querymax(lson,l_ran,r_ran);
}
if(r_ran > mid){
int tid = querymax(rson,l_ran,r_ran);
if(id != 0){
if(a[id] < a[tid])
id = tid;
}else{
id = tid;
}
}
return id;
}
void dfs(int l, int r){
if(l > r) return;
int idmin, idmax;
idmin = querymin(1,1,n,l,r);
idmax= querymax(1,1,n,l,r);
if(idmax < idmin)
swap(idmin,idmax);
LL tmp = a[idmax]*a[idmin];
for(int i = idmax-idmin+1; i <= r-l+1; i++){
ans[i] = max(ans[i], tmp);
}
if(a[idmax] > a[idmin]){
dfs(l,idmin-1);
dfs(idmin+1,r);
}else{
dfs(l,idmax-1);
dfs(idmax+1,r);
}
}
int main(){
while(scanf("%d",&n)!=EOF){
LL ret = 0;
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i]);
}
buildtree(1,1,n);
for(int i = 1; i <= n; ++i){
ans[i] = 1;
}
dfs(1,n);
for(int i = 1; i <= n; i++){
printf("%lld\n",ans[i]);
}
}
return 0;
} /*
5
5 1 2 4 4 */

  

 

HDU 5696 ——区间的价值——————【线段树、快排思想】的更多相关文章

  1. HDU 5700 区间交 离线线段树

    区间交 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5700 Description 小A有一个含有n个非负整数的数列与m个区间.每个区间可以表示为 ...

  2. hdu 5696 区间的价值 单调栈+rmq

    区间的价值 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem D ...

  3. HDU 5696 区间的价值 暴力DFS

    Problem Description 我们定义"区间的价值"为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 现在聪明的杰西想要知 ...

  4. [hdu] 5696 区间的价值 || 序列分治

    原题 我们定义"区间的价值"为一段区间的最大值*最小值. 一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1). 求长度分别为1-n的区间的最大价值. 保证数据随机 因 ...

  5. HDU 5700 区间交(线段树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5700 [题目大意] 给出一个长度为n的数列和m个区间,现在求k个区间,使得他们的区间交内的数列项和 ...

  6. HDU 5696 区间的价值 暴力

    分析:枚举以该点为最小值,然后找到最大值,更新,相应数组,至此,把区间分割(因为包含这个最小值点已经枚举过) 然后理解理解,感觉好像挺对的...因为后面(即dfs区间变小时)如果再包含最小值节点,也不 ...

  7. hdu 5696 区间的价值

    套路题 求出来以每个数为最大值/最小值时的一个区间范围, 然后枚举每个数为最大值的情况更新即可, 但是对于重复数的话需要特判一下, 假如用map记录来特判复杂度就是$O(nlogn)$, 不过题目说了 ...

  8. HDU 5700——区间交——————【线段树+枚举】

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  9. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

随机推荐

  1. 疑难杂症--单回话下 WITH(NOLOCK)返回更多数据

    ​场景:某DBA在一个人操作数据库时发现,可提交读事务隔离级别下返回的数据少于未提交读事务隔离级别,确认没有其他事务修改数据. 解决方案1: 将数据查询放入一个新建的表,使用该表查询发现问题被消除. ...

  2. 异步编程async/await

    什么是异步? 在异步程序中,程序代码不需要按照编写时的顺序严格执行,有时需要一在一个新的线程中运行一部分代码,有时无需创建新的 线程,但是为了更好的利用单个线程的能力,需要改变代码的执行顺序. 进程 ...

  3. luogu AC自动机(模板)

    完全忘了AC自动机怎么写了qwq,更别说AC自动机上DP了. 今天就好好地学习字符串好了qwq 提一下AC自动机的时间复杂度--设n是模式串的个数,m是文本串的长度,l是模式串的平均长度,那么它的时间 ...

  4. 选项卡tab2

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 洛谷P5211 [ZJOI2017]字符串(线段树+乱搞)

    题面 传送门 题解 为什么大佬们全都是乱搞的--莫非这就是传说中的暴力能进队,乱搞能AC-- 似乎有位大佬能有纯暴力+玄学优化\(AC\)(不算上\(uoj\)的\(Hack\)数据的话--这要是放到 ...

  6. SQLMAP 基础操作

    SQLMAP 基础操作 sudo git clone https://github.com/sqlmapproject/sqlmap GET 请求: -u POST 请求: Option: --dat ...

  7. dbproxy-user/pwd

    dbproxy 的账号是统一的, 即连接dbproxy,连接主mysql ,连接从mysql 的账号必须一样, 为了隔离 即使用dbproxy的人感知不到mysql, 需要分离 配置文件 #dbpro ...

  8. HTML-▲▲video 视频标签全属性详解▲▲

    HTML 5 video 视频标签全属性详解   现在如果要在页面中使用video标签,需要考虑三种情况,支持Ogg Theora或者VP8(如果这玩意儿没出事的话)的(Opera.Mozilla.C ...

  9. Echo团队Alpha冲刺随笔 - 第七天

    项目冲刺情况 进展 服务器部署完成.小程序改了几个BUG,WEB端大部分完成,后端主体功能大致完成. 问题 交接的时候出现很多新问题 心得 软工实践真棒!yeah!!! 今日会议内容 黄少勇 今日进展 ...

  10. requests库的使用

     requests库的使用 pip快速安装 pip install requests 请求方法 每一个请求方法都有一个对应的API,比如GET请求就可以使用get()方法: import reques ...