zoukankan      html  css  js  c++  java
  • bzoj2259 [Oibh]新型计算机

    [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<bits/stdc++.h>
    #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;
    }
    
    
    心如花木,向阳而生。
  • 相关阅读:
    yum源服务器搭建
    hadoop常用的端口配置
    yarn组建端口
    linux上go环境配置
    mysql主从复制
    一篇比较好的F5配置介绍
    统计随机数出现个数与直方图显示的C实现
    [LinuxC-笔记1]
    [转]达夫设备(Duff's device)
    [转]Ubuntu 18.04设置1920*1080
  • 原文地址:https://www.cnblogs.com/LLppdd/p/9231410.html
Copyright © 2011-2022 走看看