题意:

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

思路:

  对于弱数据:维护一个从左到右的最大差价和最小值。即当发现当前值比最小值小的时候更新最小值,否则看一下当前值与之前最小值的差价是否比最大差价大,是就更新最大差价。时间复杂度是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. AIX用户管理

    用户和组管理     /etc/passwd     /etc/security/.profile     /etc/security/limits     /etc/security/passwd ...

  2. C# 它 抽象类和接口

    抽象类 C#同意把类和方法声明为abstract,即抽象类和抽象方法.抽象类通常代表一个抽象概念,它提供一个继承的出发点,当设计一个新的对象类时,一定是用来继承的,所以,在一个以继承关系形成的等级结构 ...

  3. lucene做简单的文件索引

    package com.mylucene; import java.io.File; import java.io.FileReader; import java.io.IOException; im ...

  4. Swift - 多线程实现方式(2) - NSOperation和NSOperationQueue

    1,Swift继续使用Object-C原有的一套线程,包括三种多线程编程技术: (1)NSThread (2)Cocoa NSOperation(NSOperation和NSOperationQueu ...

  5. 安装Oracle时可能碰到的常见问题-1

    安装Oracle可能有些人觉得是一件非常easy的事情,但事实上是在安装的过程中蕴含着丰富的知识点.尤其安装在Linux平台,可能会碰到这样或那样各种诡异的问题,透过问题看到本质,这才是从深处理解Or ...

  6. innerXml,outerXml,innerText的不同

    原文:innerXml,outerXml,innerText的不同 昨天看到咱们园子里有一个仁兄写的关于xml的有关操作,在读的过程中,由于是初学者有不明白的地方就查资料,发现自己多innerXml, ...

  7. Mongdb 访问

    http://114.55.75.xx/pics/201607040751367d21a38035bd4da7abd4473783f85f7a

  8. Spring的事件处理

    Spring对事件有一些支持,因为项目须要,所以近期小小研究了下究竟这个怎么能够方便的用在实际项目其中来. 说起事件这个东西,事实上就是借鉴的那个观察者模式.这里面涉及到事件源.事件监听者.事件公布者 ...

  9. Extract Datasets

    *&---------------------------------------------------------------------* *& Report ZTEST2013 ...

  10. 特殊的Windows消息

    WM_CREATE消息 该消息是Windows发送给视图的第一个消息.由于当应用程序框架调用Create函数时该消息就会被发送,而此时窗口创建还未完成,窗口还不可见,因此在控制函数OnCreate内部 ...