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 ...
随机推荐
- pyhton3 sys模块
Python常用模块之sys sys模块提供了一系列有关Python运行环境的变量和函数. 1 ). sys.stdin 标准输入流.2 ).sys.stdout 标准输出流.3 ). sys.std ...
- Hibernate多对多关联
多对多关联: 示例:Teacher和Student,一个Teacher可以教很多student,一个Student也可以被很多teacher教 多对多单向关联 Teacher知道自己教了哪些学生, ...
- Oracle索引表
索引组织表(Index-Organized Table)是按B-树的结构来组织和存储数据的.与标准表中的数据时无序存放的不同,索引表中数据按主键值有序存储. 叶子节点中存放的是表的主键值与所有非主键值 ...
- java WordUtils word文档工具类
package com.sicdt.library.core.utils; import java.io.ByteArrayOutputStream; import java.io.IOExcepti ...
- p2p网络中的NAT穿透技术----常见NAT穿越解决方案
转:http://blog.csdn.net/cllzw/article/details/46438257 常见NA丁穿越解决方案 NAT技术在缓解IPv4地址紧缺问题.构建防火墙.保证网络安全等方面 ...
- ceph安装各种报错
[ceph_deploy][ERROR ] RuntimeError: Failed to execute command: ceph-disk-activate –mark-init sysvini ...
- java深入探究12-框架之Structs
注意每次修改配置文件后必须项目重启 Structs2=structs1+xwork Struct2框架预先实现了一些功能: 1.请求数据的封装:2.文件上传的功能3.对国际化功能的简化4.文件效验功能 ...
- 初探MyBatis之HelloWorld(二)
二.不使用 XML 构建 SqlSessionFactory 不使用xml构建SqlSessionFactory的话,就要用java代码来连接数据库.我这里直接new DataSorce()接口实现g ...
- Spring学习之xml配置Bean总结
学习Spring时,我用的是Maven来管理jar包,先看看maven的pom.xml: pom.xml <project xmlns="http://maven.apache.org ...
- Spring AOP的一个比喻和IOC的作用
aop切面编程就是在常规的执行java类中方法前或执行后加入自定义的方法.比如你本来每天都去打酱油,去,打酱油,回.现在我每天在你打酱油路上等着,你去打酱油的时候我打你一顿,回来的时候给你点糖果吃.你 ...