• 【BZOJ】3427: Poi2013 Bytecomputer


    题意:

    给定一个长度为(n)({-1, 0, 1})组成的序列,你可以进行(x_i=x_i+x_{i-1})这样的操作,求最少操作次数使其变成不降序列。((n le 1000000)

    分析:

    我们考虑第(i)个数,如果(x_i < x_{i-1}),要想(x_i ge x_{i-1}),那么(x_i)至少要加一次(x_{i-1})才能大过(x_{i-1})(当然(x_{i-1} < 0)那么永远不可能了)。

    题解

    然后我们猜测,最终的最优序列也一定由(\{-1, 0, 1\})三个数组成。我们来证明一下:
    假设第一个不是(\{-1, 0, 1\})数的位置为(p),且假设(p < n),则容易知道(x_p > 1)。当(x_{p+1} = -1)时,我们要加2次才能大于等于(x_p),当(x_{p+1}=0或1)时,我们要加1次。而由于(x_p > 1),那么说明(x_p)也一定能够等于(1),这是因为(x_{p-1})必然等于(1)(否则(x_p)就不会大于(1))。而当(x_p=1)时,对于(x_{p+1} in \{-1, 0, 1\})我们分别只需要加2次、加1次和加0次就能满足(x_{p+1} ge x_p)。显然比(x_p > 1)要优。得证。
    于是我们设(d[i, j])表示前(i)个元素当前元素为(j)时的最少操作次数,然后推一下就行了..

    #include <bits/stdc++.h>
    using namespace std;
    const int oo=~0u>>1;
    int n, d[2][3];
    
    int main() {
    	scanf("%d", &n);
    	int x; scanf("%d", &x);
    	int *now=d[0], *last=d[1];
    	last[0]=last[1]=last[2]=oo;
    	if(x==-1) last[0]=0;
    	if(x==0) last[1]=0;
    	if(x==1) last[2]=0;
    	for(int i=2; i<=n; ++i) {
    		scanf("%d", &x);
    		now[0]=now[1]=now[2]=oo;
    		if(last[0]!=oo) {
    			now[0]=last[0]+x+1;
    			if(x>=0) now[1]=last[0]+x;
    			if(x==1) now[2]=last[0];
    		}
    		if(last[1]!=oo) {
    			if(x==0) now[1]=min(now[1], last[1]);
    			if(x==1) now[2]=min(now[2], last[1]);
    		}
    		if(last[2]!=oo) {
    			now[2]=min(now[2], last[2]+1-x);
    		}
    		swap(now, last);
    	}
    	swap(now, last);
    	int ans=min(min(now[0], now[1]), now[2]);
    	if(ans==oo) puts("BRAK");
    	else printf("%d
    ", ans);
    	return 0;
    }
  • 相关阅读:
    【SQLSERVER学习笔记】进攻式编程
    jQuery插件开发全解析
    淘宝前端框架kissyui
    JS获取MVC Attrbuate验证是否通用
    Asp.net MVC 自定义错误页面以及return HttpNotFound遇到的问题
    为类型“xxxx”多次调用了 Map,且其中至少有一个调用未指定目标表名称。
    Entity FreamWork 无法创建“System.Object”类型的常量值。此上下文仅支持基元类型或枚举类型错误解决
    Scala集合
    Scala面向对象
    scala函数
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4985818.html
Copyright © 2020-2023  润新知