ACM学习历程—广东工业大学2016校赛决赛-网络赛E 积木积水(最值问题 || 动态规划)
2016-04-10 20:14
190 查看
题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=4
这个题目自然会考虑到去讨论最长或者最短的板子。
笔上大概模拟一下的话,就会知道,假设最长的板子是r,0和n+1位置上都是高度为0的板子,那么对于[0, r-1]中的最长板子rr,rr到r这一短应该都是被深度为a[rr]的水覆盖。同样的[0, rr-1]中的最长板子rrr,rrr到rr这一段应该是被a[rrr]覆盖,以此类推可以搞定r的前面一段,同理搞定后一段。
关于最值这一块,可以使用RMQ之类的logn维护,总的复杂度是nlogn。但是考虑到区间都是[0, r]和[r, n+1]这种的。所以很容易想到DP,p[0][i]表示从0到i区间内最大值的角标,p[1][i]表示从i到n+1区间内最大值的角标。然后两遍方程转移。总的复杂度是O(n)。
代码:
View Code
这个题目自然会考虑到去讨论最长或者最短的板子。
笔上大概模拟一下的话,就会知道,假设最长的板子是r,0和n+1位置上都是高度为0的板子,那么对于[0, r-1]中的最长板子rr,rr到r这一短应该都是被深度为a[rr]的水覆盖。同样的[0, rr-1]中的最长板子rrr,rrr到rr这一段应该是被a[rrr]覆盖,以此类推可以搞定r的前面一段,同理搞定后一段。
关于最值这一块,可以使用RMQ之类的logn维护,总的复杂度是nlogn。但是考虑到区间都是[0, r]和[r, n+1]这种的。所以很容易想到DP,p[0][i]表示从0到i区间内最大值的角标,p[1][i]表示从i到n+1区间内最大值的角标。然后两遍方程转移。总的复杂度是O(n)。
代码:
#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 = 1e6+5; int n, a[maxN]; //RMQ-ST算法 //效率nlogn //查询区间最值,注意区间[0, n-1]和[1, n]的区别 int ma[maxN][20]; void RMQ() { memset(ma, 0, sizeof(ma)); for (int i = 0; i <= n+1; ++i) ma[i][0] = i; for (int j = 1; (1<<j) <= n+2; ++j) for (int i = 0; i+(1<<j)-1 <= n+1; ++i) { if (a[ma[i][j-1]] > a[ma[i+(1<<(j-1))][j-1]]) ma[i][j] = ma[i][j-1]; else ma[i][j] = ma[i+(1<<(j-1))][j-1]; } } int query(int lt, int rt) { int k = 0; while ((1<<(k+1)) <= rt-lt+1) k++; if (a[ma[lt][k]] > a[ma[rt-(1<<k)+1][k]]) return ma[lt][k]; else return ma[rt-(1<<k)+1][k]; } void input() { scanf("%d", &n); a[0] = a[n+1] = 0; for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); RMQ(); } LL cal(int lt, int rt, int h) { LL ans = 0; for (int i = lt; i <= rt; ++i) ans += max(0, h-a[i]); return ans; } void work() { LL ans = 0; int mid = query(0, n+1), k, now; now = mid; while (now > 0) { k = query(0, now-1); ans += cal(k, now-1, a[k]); now = k; } now = mid; while (now < n+1) { k = query(now+1, n+1); ans += cal(now+1, k, a[k]); now = k; } cout << ans << endl; } int main() { //freopen("test.in", "r", stdin); int T; scanf("%d", &T); for (int times = 1; times <= T; ++times) { input(); work(); } return 0; }
View Code
相关文章推荐
- 【Android基础】网络图片查看器
- HDU 4975 A simple Gaussian elimination problem网络流
- 关于编写网络技术文档的基本步骤
- ACM学习历程—广东工业大学2016校赛决赛-网络赛C wintermelon的魔界寻路之旅(最短路 && 递推)
- 采用TCP协议的PIC32MZ ethernet bootloader
- HTTP协议格式
- HTTP报文结构
- HTTP 411 Content-Length required
- 编写新闻客户端&网络编程day1(66期第四天)
- ios解决http上传乱码问题
- Http请求头探讨
- 神经网络指南Hacker's guide to Neural Networks
- BP神经网络原理及编程实现
- 卷积神经网络Convolutional Neural Networks
- 深度卷积神经网络用于图像缩放Image Scaling using Deep Convolutional Neural Networks
- TCP漏洞:半连接
- 用matlab训练数字分类的深度神经网络Training a Deep Neural Network for Digit Classification
- TCP协议三次握手连接四次握手断开和DOS攻击
- 深度神经网络入门教程Deep Neural Networks: A Getting Started Tutorial
- 深度神经网络如何看待你,论自拍What a Deep Neural Network thinks about your #selfie