博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2259 [Oibh]新型计算机
阅读量:5086 次
发布时间:2019-06-13

本文共 2363 字,大约阅读时间需要 7 分钟。

[Oibh]新型计算机

Time Limit: 6 Sec Memory Limit: 128 MB

Description

Tim正在摆弄着他设计的“计算机”,他认为这台计算机原理很独特,因此利用它可以解决许多难题。

但是,有一个难题他却解决不了,是这台计算机的输入问题。新型计算机的输入也很独特,假设输入序列中有一些数字(都是自然数——自然数包括0),计算机先读取第一个数字S1,然后顺序向后读入S1个数字。接着再读一个数字S2,顺序向后读入S2个数字……依此类推。不过只有计算机正好将输入序列中的数字读完,它才能正确处理数据,否则计算机就会进行自毁性操作!
Tim现在有一串输入序列。但可能不是合法的,也就是可能会对计算机造成破坏。于是他想对序列中的每一个数字做一些更改,加上一个数或者减去一个数,当然,仍然保持其为自然数。使得更改后的序列为一个新型计算机可以接受的合法序列。
不过Tim还希望更改的总代价最小,所谓总代价,就是对序列中每一个数操作的参数的绝对值之和。
写一个程序:
 从文件中读入原始的输入序列;
 计算将输入序列改变为合法序列需要的最小代价;
 向输出文件打印结果。

Input

输入文件包含两行,第一行一个正整数N,N<1 000 001。

输入文件第二行包含N个自然数,表示输入序列。

Output

仅一个整数,表示把输入序列改变为合法序列需要的最小代价,保证最小代价小于109。

Sample Input

4

2 2 2 2

Sample Output

1

\(f[i]\) 表示处理 \(i\)\(n\) 的最优答案。
显然 \(f[i] = min \{ f[j] + abs{(j - i - 1) - a[i]} \}\ \ \ (i<j<n)\)
我们把这个式子打开
\(f[i] = min(f[j]+j)-(i+1+a[i])\ \ \ (j ≥ a[i]+i+1)\)
\(f[i] = min(f[j]-j)+(i+1+a[i])\ \ \ (j<a[i]+i+1)\)
然后我们分别用两个树状数组维护一下 \(f[j]+j\)\(f[j]-j\) 就好了

#include
#define lowbit(x) ((x) & (-x))using namespace std;const int maxn = 1e6 + 6, INF = 1e9 + 9;int n, ini[maxn], f[maxn], tree1[maxn], tree2[maxn];inline int read() { char ch = getchar(); int x = 0, f = 1; while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} while('0' <= ch && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();} return x * f;}inline int query2(int t){ int ret = INF; if(t > n || t <= 0) return ret; while(t){ ret = min(ret, tree2[t]); t -= lowbit(t); } return ret;}inline int query1(int t){ int ret = INF; t = (n + 1) - t; if(t > n || t <= 0) return ret; while(t){ ret = min(ret, tree1[t]); t -= lowbit(t); } return ret;}inline void Modify(int t){ int lin = t; while(lin <= n){ tree2[lin] = min(tree2[lin], f[t] - t); lin += lowbit(lin); } lin = (n + 1) - t; while(lin <= n){ tree1[lin] = min(tree1[lin], f[t] + t); lin += lowbit(lin); }}int main(){ scanf("%d", &n); int t; memset(tree1, 0x3f, sizeof(tree1)); memset(tree1, 0x3f, sizeof(tree1)); for(int i = 1; i <= n; ++i) ini[i] = read(); for(int i = n; i >= 1; --i){ f[i] = abs(n - i - ini[i]); t = ini[i] + i + 1; if(t < n) f[i] = min(f[i], query1(t) - t); f[i] = min(f[i], query2(t) + t); Modify(i); } cout << f[1]; return 0;}

转载于:https://www.cnblogs.com/LLppdd/p/9231410.html

你可能感兴趣的文章
也谈设计模式,架构,框架和类库的区别
查看>>
算法入门经典大赛 Dynamic Programming
查看>>
java爬取Excel表格
查看>>
C#开发微信公众号-学习笔记
查看>>
关于HibernateTempleate模版-很多代码可以直接使用,是开发人员不可多得选择
查看>>
购物商城+ATM
查看>>
基因组共线性分析方法
查看>>
Java导包——import语句
查看>>
StringBuffer类
查看>>
20181113-1 版本控制报告
查看>>
luogu3146 [USACO16OPEN]248
查看>>
Notes of the scrum meeting(2013/10/20)
查看>>
uva 11054 wine trading in gergovia (归纳【好吧这是我自己起的名字】)——yhx
查看>>
管理系统
查看>>
Oracle性能优化随笔
查看>>
JavaScrip写的贪吃蛇
查看>>
Jzoj4732 函数
查看>>
Jzoj5453【NOIP2017提高A组冲刺11.5】好路线
查看>>
OPENGL ES2.0如何不使用glActiveTexture而显示多个图片
查看>>
Linux /proc、/dev Principle
查看>>