ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=5696
这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了。加上2A的时候差了一题,当时有思路,但是代码就是过不去。。这次应该是无缘复赛了。。
先不水了,省赛回来,我看了一下这个题,当时有个类似于快排的想法,今天试了一下,勉强AC了。。跑了3S多。
思路就是我枚举区间左值lt,那么[lt, n]区间内最值的角标分别为mi和ma。于是设to = max(mi, ma)。也就是说在to右侧的所有区间[lt, i]的值至少都是a[mi]*a[ma]。用线段树维护长度为i区间的最值,那么我需要用a[mi]*a[ma]去更新区间[to-lt+1, rt-lt+1]在线段树中的值。然后区间就可以缩减为[lt, to-1]了,于是递归求解就可以了,当然此处可以迭代。
关键是上述的递归过程最多需要运行多少次?
首先to这个位置,要么是mi,要么是ma,也就是说左侧的数据要么都比to这个位置的数小,要么都比它大。光看左侧,这个to很像快排一次运行的那个分隔值。那么to平均下来应该是(lt+rt)/2。
那么总的复杂度就是nlognlogn.
但是此处线段树常数较大,所以需要减一下枝,就是当更新值pls比子树中任意值都小,就可以不用更新,维护子树的最小值就可以了。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long using namespace std; const int maxN = ;
int n, a[maxN]; //RMQ-ST算法
//效率nlogn
//查询区间最值,注意区间[0, n-1]和[1, n]的区别
int ma[maxN][], mi[maxN][]; void RMQ()
{
memset(ma, , sizeof(ma));
memset(mi, , sizeof(mi));
for (int i = ; i <= n; ++i)
mi[i][] = ma[i][] = i;
for (int j = ; (<<j) <= n; ++j)
for (int i = ; i+(<<j)- <= n; ++i)
{
if (a[ma[i][j-]] >= a[ma[i+(<<(j-))][j-]])
ma[i][j] = ma[i][j-];
else
ma[i][j] = ma[i+(<<(j-))][j-];
if (a[mi[i][j-]] <= a[mi[i+(<<(j-))][j-]])
mi[i][j] = mi[i][j-];
else
mi[i][j] = mi[i+(<<(j-))][j-];
}
} int queryMax(int lt, int rt)
{
int k = ;
while ((<<(k+)) <= rt-lt+)
k++;
if (a[ma[lt][k]] >= a[ma[rt-(<<k)+][k]])
return ma[lt][k];
else
return ma[rt-(<<k)+][k];
} int queryMin(int lt, int rt)
{
int k = ;
while ((<<(k+)) <= rt-lt+)
k++;
if (a[mi[lt][k]] <= a[mi[rt-(<<k)+][k]])
return mi[lt][k];
else
return mi[rt-(<<k)+][k];
} //线段树
//求区间最值
struct node
{
int lt, rt;
LL val, delta;
}tree[*maxN]; //向下更新
void pushDown(int id)
{
if (tree[id].delta != )
{
tree[id<<].val = tree[id<<].delta = max(tree[id<<].val, tree[id].delta);
tree[id<<|].val = tree[id<<|].delta = max(tree[id<<|].val, tree[id].delta);
tree[id].delta = ;
}
} //向上更新
void pushUp(int id)
{
tree[id].val = min(tree[id<<].val, tree[id<<|].val);
} //建立线段树
void build(int lt, int rt, int id)
{
tree[id].lt = lt;
tree[id].rt = rt;
tree[id].val = ;//每段的初值,根据题目要求
tree[id].delta = ;
if (lt == rt)
{
//tree[id].delta = ??;
return;
}
int mid = (lt+rt)>>;
build(lt, mid, id<<);
build(mid+, rt, id<<|);
} //增加区间内每个点固定的值
void change(int lt, int rt, int id, LL pls)
{
if (pls <= tree[id].val) return;
if (lt <= tree[id].lt && rt >= tree[id].rt)
{
tree[id].val = tree[id].delta = max(tree[id].delta, pls);
return;
}
pushDown(id);
int mid = (tree[id].lt+tree[id].rt)>>;
if (lt <= mid)
change(lt, rt, id<<, pls);
if (rt > mid)
change(lt, rt, id<<|, pls);
pushUp(id);
} //查询某段区间内的最值
LL query(int lt, int rt, int id)
{
if (lt <= tree[id].lt && rt >= tree[id].rt)
return tree[id].val;
pushDown(id);
int mid = (tree[id].lt+tree[id].rt)>>;
if (rt <= mid)
return query(lt, rt, id<<);
if (lt > mid)
return query(lt, rt, id<<|);
return max(query(lt, mid, id<<), query(mid+, rt, id<<|));
} void input()
{
for (int i = ; i <= n; ++i) scanf("%d", &a[i]);
RMQ();
build(, n, );
} int cnt; void cal(int lt, int rt)
{
int to, mi, ma;
while (lt <= rt)
{
mi = queryMin(lt, rt);
ma = queryMax(lt, rt);
to = max(mi, ma);
change(to-lt+, rt-lt+, , (LL)a[mi]*a[ma]);
rt = to-;
}
} void work()
{
cnt = ;
for (int i = ; i <= n; ++i)
cal(i, n);
for (int i = ; i <= n; ++i)
printf("%lld\n", query(i, i, ));
} int main()
{
//freopen("test.out", "w", stdout);
//freopen("test.in", "r", stdin);
while (scanf("%d", &n) != EOF)
{
input();
work();
}
return ;
}
ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)的更多相关文章
- ACM学习历程—Codeforces 446C DZY Loves Fibonacci Numbers(线段树 && 数论)
Description In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence ...
- ACM学习历程——HDU2227 Find the nondecreasing subsequences(线段树 && dp)
Description How many nondecreasing subsequences can you find in the sequence S = {s1, s2, s3, ...., ...
- ACM学习历程——POJ3321 Apple Tree(搜索,线段树)
Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will ...
- ACM学习历程—HDU5700 区间交(树状数组 && 前缀和 && 排序)
http://acm.hdu.edu.cn/showproblem.php?pid=5700 这是这次百度之星初赛2B的第五题.省赛回来看了一下,有这样一个思路:对于所有的区间排序,按左值排序. 然后 ...
- ACM学习历程—HDU5592 ZYB's Premutation(逆序数 && 树状数组 && 二分)(BestCoder Round #65 1003)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5592 题目大意就是给了每个[1, i]区间逆序对的个数,要求复原原序列. 比赛的时候2B了一发. 首先 ...
- ACM学习历程—HDU 5536 Chip Factory(xor && 字典树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536 题目大意是给了一个序列,求(si+sj)^sk的最大值. 首先n有1000,暴力理论上是不行的. ...
- ACM学习历程—HDU 5443 The Water Problem(RMQ)(2015长春网赛1007题)
Problem Description In Land waterless, water is a very limited resource. People always fight for the ...
- ACM学习历程——UVA11234 Expressions(栈,队列,树的遍历,后序遍历,bfs)
Description Problem E: Expressions2007/2008 ACM International Collegiate Programming Contest Unive ...
- ACM学习历程—HDU 5317 RGCDQ (数论)
Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more an ...
随机推荐
- iOS11 仿大标题 导航栏
iOS11 SytleTitleController 仿大标题 风格 导航栏 仿 iOS11 大导航标题 风格 UI 适用范围 iOS8 + 前言 iOS11全面应用大标题设计,(岂止于大—— 比逼 ...
- flask实现模仿知乎
上个月花了一个月的时间学习flask框架实现了一个简陋的知乎,有提问,回答,写文章,个人信息页,个人信息修改等功能,因刚接触学习flask,后端代码实现很多冗余,依旧需要修改. github: htt ...
- 何为RunLoop?RunLoop有哪些应用场景?
一.RunLoop的作用 一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件发生 ...
- vRO 添加已有磁盘到VM
在vRO实现将已有虚拟机磁盘添加到另外的虚拟机上,以为vRA发布Oracle/SQL集群做准备: // 脚本需要两个输入 vm_obj和diskPathSystem.log("Attempt ...
- SQLite3时间函数小结
import sqlite3 conn = sqlite3.connect('/tmp/sqlite.db') cur = conn.cursor() 接下来干嘛呢?建一张表吧.这里需要注意的是,SQ ...
- Python 数值类型
1.数值类型分为整形(二进制(0b),八进制(0o),十进制,十六进制(0x) ),浮点型,long,complex(复合行) 当我们说十进制数的时候,是逢10进1,就是说到达10的时候就要向前一位进 ...
- poj 2406 Power Strings【字符串+最小循环节的个数】
Po ...
- codeforces 353D 递推 找规律
题意:一组男生女生在排队,每秒钟所有排在女生左边的男生与她相邻的女生交换位置,求女生全部换到男生前面的时间. 思路: 解法一:队伍最前面的那些女生不需要交换,后面的女生有两种状态:畅通无阻,前一个女生 ...
- java异常和错误类总结(2016.5)
看到以前2016.5.写的一点笔记,拿过来放在一起. java异常和错误类总结 最近由于考试和以前的面试经常会遇到java当中异常类的继承层次的问题,弄得非常头大,因为java的异常实在是有点多,很难 ...
- Could not reserve enough space for object heap解决办法
Centos6.4 Jdk1.6 1.在终端输入Java命令报错 [root@localhost local]# java Error occurred during initialization ...