UVALive 6087 Fuel Stops(思维、数环上任意前缀和非负的点个数)
2016-07-02 09:15
477 查看
题目链接:
UVALive 6087 Fuel Stops
题意:
有n个城市,要做一次环游,每到一个城市可以增加一定的油量同时也会消耗一定的油量,要保证环游过程中到每个城市的油量非负,选择起点城市有多少个?保证有解。(n≤105)
分析:
可以把每个城市的增加油量和消耗油量先相减,那么其实就是求数环上任意前缀和都非负的点有多少个?
我们先从第一个城市开始,找到第一个满足条件(从当前位置到n−1的前缀和都是非负)的城市st,用pre[]表示前缀和,对于从0到st之间的任意城市i都是不满足条件的,因为到达i之前的油量是非负的,同时i后面会出现前缀和为负数,那么单单从i开始肯定也是负数的。对于从st+1→n−1的位置的城市,用Min[i]表示从0→i位置的前缀和最小值,用suf[i]表示从n−1→i的后缀和最小值,此时pre[i]就是从st开始的前缀和。那么显然需要满足suf[i]−pre[i−1]>=0且Min[i−1]+pre[n−1]−pre[i−1]>=0的城市i才符合条件。
UVALive 6087 Fuel Stops
题意:
有n个城市,要做一次环游,每到一个城市可以增加一定的油量同时也会消耗一定的油量,要保证环游过程中到每个城市的油量非负,选择起点城市有多少个?保证有解。(n≤105)
分析:
可以把每个城市的增加油量和消耗油量先相减,那么其实就是求数环上任意前缀和都非负的点有多少个?
我们先从第一个城市开始,找到第一个满足条件(从当前位置到n−1的前缀和都是非负)的城市st,用pre[]表示前缀和,对于从0到st之间的任意城市i都是不满足条件的,因为到达i之前的油量是非负的,同时i后面会出现前缀和为负数,那么单单从i开始肯定也是负数的。对于从st+1→n−1的位置的城市,用Min[i]表示从0→i位置的前缀和最小值,用suf[i]表示从n−1→i的后缀和最小值,此时pre[i]就是从st开始的前缀和。那么显然需要满足suf[i]−pre[i−1]>=0且Min[i−1]+pre[n−1]−pre[i−1]>=0的城市i才符合条件。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <climits> #include <cmath> #include <ctime> #include <cassert> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); using namespace std; typedef long long ll; const int MAX_N = 100010; int n, cases = 0, total, st; int data[MAX_N], pre[MAX_N], sum[MAX_N], suf[MAX_N], ans[MAX_N], Min[MAX_N]; int main() { while(~scanf("%d", &n) && n) { for(int i = 0; i < n; ++i) scanf("%d", &data[i]); st = total = 0; for(int i = 0; i < n; ++i) { int tmp; scanf("%d", &tmp); data[i] -= tmp; sum[i] = sum[i - 1] + data[i]; if(i == 1) Min[1] = data[1]; else Min[i] = min(Min[i - 1], sum[i]); } pre[0] = data[0]; for(int i = 1; i < n; ++i) { if(pre[i - 1] < 0) { pre[i - 1] = 0; st = i; } pre[i] = pre[i - 1] + data[i]; } ans[total++] = st; suf[n - 1] = pre[n - 1]; for(int i = n - 2; i > st; --i) { suf[i] = min(suf[i + 1], pre[i]); } for(int i = st + 1; i < n; ++i) { if(suf[i] - pre[i - 1] >= 0 && Min[i - 1] + pre[n - 1] - pre[i - 1] >= 0) ans[total++] = i; } printf("Case %d:", ++cases); for(int i = 0; i < total; ++i) { printf(" %d", ans[i] + 1); } printf("\n"); } return 0; }
相关文章推荐
- 快速学习JavaScript的6个思维技巧
- 暗时间读书笔记
- 思维和经验哪个更重要?看懂这个可以比别人少奋斗5年!
- 跳不出思维的惯性模式,何谈颠覆?【读历史知创业】
- 你有没有意识到,计算时代已经悄然降临
- 穷人的饥饿思维
- 思维定势
- 关联性思维和给客户展示功能
- 经典的售前思维题目,一个很经典的故事
- 变革思维
- 肯定式探询---组织发展和变革中的积极思维方式
- 从使用Python开发一个Socket示例说到开发者的思维和习惯问题
- 独立思考者模型:避开思维误区的沼泽
- 从两个回复看男性思维与女性思维的区别
- 编程思想——面向对象架构梦想
- 1.去京城的阻碍 。
- 他们的职业分别是什么?
- 浅谈局部思维的误区
- 为什么要学习英语?