题意:

  在给出的区间内求出最大买进卖出的差价。

思路:

  对于弱数据:维护一个从左到右的最大差价和最小值。即当发现当前值比最小值小的时候更新最小值,否则看一下当前值与之前最小值的差价是否比最大差价大,是就更新最大差价。时间复杂度是O(m*n)

   对于强数据:利用线段树维护一个最大差价、最大值和最小值,查询的时候求出询问的范围内左右子树的最大差价,然后再利用RMQ求出[l, mid]的最小值和[mid+1, r]的最大值,然后返回max(df[rt<<1], df[rt<<1|1], RMQ(mid+1, r)-RMQ(l, mid));这个的时间复杂度是O(nlgn)+m*O(nlgn)

Tips:

  我的做法是维护了最大值和最小值以便求出最大差值,也可以不维护这个,直接利用RMQ求出最大值和最小值,然后求最大差值。

Code:

 #include <stdio.h>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std; const int MAXN = ;
int mx[MAXN<<], mn[MAXN<<], df[MAXN<<];
int dpx[MAXN][], dpn[MAXN][];
int val[MAXN]; void makermq(int n)
{
for (int j = ; (<<j) <= n; ++j)
for (int i = ; i+(<<j)- <= n; ++i) {
dpn[i][j] = min(dpn[i][j-], dpn[i+(<<(j-))][j-]);
dpx[i][j] = max(dpx[i][j-], dpx[i+(<<(j-))][j-]);
}
} int rmqx(int s, int v)
{
int k = (int)(log((v-s+)*1.0)/log(2.0));
return max(dpx[s][k], dpx[v-(<<k)+][k]);
} int rmqn(int s, int v)
{
int k = (int)(log((v-s+)*1.0)/log(2.0));
return min(dpn[s][k], dpn[v-(<<k)+][k]);
} void PushUp(int rt)
{
mx[rt] = max(mx[rt<<], mx[rt<<|]);
mn[rt] = min(mn[rt<<], mn[rt<<|]);
df[rt] = max(df[rt<<], df[rt<<|]);
df[rt] = max(df[rt], mx[rt<<|]-mn[rt<<]);
} void Build(int rt, int l, int r)
{
if (l == r) {
scanf("%d", &mx[rt]);
mn[rt] = mx[rt];
dpn[l][] = dpx[l][] = mx[rt];
return;
}
int mid = (l+r)/;
Build(rt<<, l, mid);
Build(rt<<|, mid+, r);
PushUp(rt);
} int query(int l, int r, int L, int R, int rt)
{
if (L >= l && R <= r) {
return df[rt];
}
int mid = (L+R)/;
int ans = ;
if (r <= mid) ans = query(l, r, L, mid, rt<<);
else if (l > mid) ans = query(l, r, mid+, R, rt<<|);
else {
ans = query(l, r, L, mid, rt<<);
ans = max(ans, query(l, r, mid+, R, rt<<|)); ans = max(ans, rmqx(mid+, r)-rmqn(l, mid));
}
return ans;
} int main()
{
//freopen("in.txt", "r", stdin);
int n;
int q, a, b;
while (~scanf("%d", &n)) {
n++;
memset(df, , sizeof(df));
memset(mx, , sizeof(mx));
memset(mn, , sizeof(mn));
Build(, , n);
makermq(n); scanf("%d", &q);
while (q--) {
scanf("%d %d", &a, &b);
a++, b++;
printf("%d\n", query(a, b, , n, ));
}
puts("");
}
return ;
}

链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1832

外传野史:这道题其实是某学长的面试题,当时那个学长太紧张了,没想清楚,只想到了可以用线段树维护最大值和最小值来解,但是面试官貌似也不认识线段树,然后提示说这个是股票,最小值必须在最大值的左面,这样单纯的维护最大值最小值就不好使了。

所以正解的确是用线段树,但是是用线段树维护差值,并用RMQ来帮忙维护 差值 = 右子树指定范围内最大值-左子树指定范围内最小值 的问题。

这个是zz想到的啦,给他一个good~

Hlg 1832 【线段树 && RMQ】.cpp的更多相关文章

  1. HDU 1754 I Hate It 线段树RMQ

    I Hate It Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=175 ...

  2. 《白书》上线段树RMQ的实现

    白书上的线段树RMQ实现,自己重写了一遍: #include <bits/stdc++.h> using namespace std; const int MAXN=1<<17 ...

  3. 单点更新线段树 RMQ

    D. Xenia and Bit Operations time limit per test 2 seconds memory limit per test 256 megabytes input ...

  4. CSU 1809 - Parenthesis - [前缀和+维护区间最小值][线段树/RMQ]

    题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1809 Bobo has a balanced parenthesis sequenc ...

  5. UVA 11235 Frequent values 线段树/RMQ

    vjudge 上题目链接:UVA 11235 *******************************************************大白书上解释**************** ...

  6. PKU 2823 Sliding Window(线段树||RMQ||单调队列)

    题目大意:原题链接(定长区间求最值) 给定长为n的数组,求出每k个数之间的最小/大值. 解法一:线段树 segtree节点存储区间的最小/大值 Query_min(int p,int l,int r, ...

  7. Zeratul的完美区间(线段树||RMQ模板题)

    原题大意:原题链接 给定元素无重复数组,查询给定区间内元素是否连续 解体思路:由于无重复元素,所以如果区间内元素连续,则该区间内的最大值和最小值之差应该等于区间长度(r-l) 解法一:线段树(模板题) ...

  8. ACM学习历程—HDU 5289 Assignment(线段树 || RMQ || 单调队列)

    Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fro ...

  9. dutacm.club_1094_等差区间_(线段树)(RMQ算法)

    1094: 等差区间 Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total ...

随机推荐

  1. 基于visual Studio2013解决C语言竞赛题之1053洗牌

       题目 解决代码及点评 /* 功能:洗扑克牌.将54张牌分别编号为1,2,-,54号,并放在数组M中. 洗牌方法如下:产生[1,54]区间内的一个随机数K,将M[1]与M[K]交换: ...

  2. 基于visual Studio2013解决C语言竞赛题之1063分橘子

       题目 解决代码及点评 /* 功能:某桔农家共有2520只桔子, 父亲要将它们分给六个儿子,其分法如下: 父亲先将2520只桔子分给六个儿子, 然后说:"老大,把你分到的桔子 ...

  3. 页面爬虫(获取其他页面HTML)加载到自己页面

    //前台 <div id="showIframe"></div> $(document).ready(function() { var url = &quo ...

  4. hdu1087Super Jumping! Jumping! Jumping!(最大递增序列和)

    题意:棋牌游戏如今,一种被称为“超级跳!跳!跳!“HDU是非常流行的.也许你是个好孩子,这个游戏知之甚少,所以我介绍给你吧. 可以玩游戏由两个或两个以上的球员 .它由一个棋盘(棋盘)和一些棋子(棋子) ...

  5. Boost Thread学习笔记二

    除了thread,boost种:boost::mutexboost::try_mutexboost::timed_mutexboost::recursive_mutexboost::recursive ...

  6. poj1066 Jugs

    poj1066 Jugs http://poj.org/problem?id=1606 解题思路:本题可以用数学方法解得,最易理解,常规的解法是搜索.直接用接近模拟的广度优先搜索即可过. 给两个容器, ...

  7. ASIHTTPRequest开源类项目导入问题及解决方法

    在静态库project中加入ASIHTTPRequest导出lib.a.放到project里编译出一下错: Undefined symbols for architecture armv7: &quo ...

  8. android onKeydown

    package wyf.ytl; import android.app.Activity; import android.content.Context; import android.os.Bund ...

  9. 14.2.5.7 Physical Row Structure 物理数据结构:

    14.2.5.7 Physical Row Structure 物理数据结构: InnoDB物理记录结构依赖行格式 在表创建的时候, 默认, InnoDB 使用Antelope 文件存储格式和它的压缩 ...

  10. Qt4在linux下的安装

    1.下载SDK ftp://ftp.informatik.hu-berlin.de/pub/Mirrors/ftp.troll.no/QT/qtsdk/qt-sdk-linux-x86-opensou ...