zoukankan      html  css  js  c++  java
  • 6562. 【GDOI2020模拟4.15】楼房搭建(building)

    题目描述

    小 H 是一个建筑师,他接到了一个任务——按照计划图搭建一排楼房。计划图上从左到右
    给出了 n 个非负整数,对于第 i 个数 h i ,它表示在 i 这个位置搭建出来的楼房的高度不能小于h i 。
    小 H 搭建楼房的方式也很特别。在每一时刻,它总可以让相邻的两个楼房分别增高 1 个单
    位和增高 2 个单位。具体地,对于任意的 i(1 ≤ i < n),每一时刻他可以有以下两种搭建的方法:
    1. 让 i 位置上的楼房的高度 +2,同时让 i + 1 位置上的楼房 +1。
    2. 让 i 位置上的楼房的高度 +1,同时让 i + 1 位置上的楼房 +2。
    小 H 想知道最快需要多少时间,搭建出来的这一排楼房才能满足计划图的要求?

    n,hi<=10^6

    题解

    贪心苦手表示很淦

    考虑一个假的贪心:每次对当前的进行+2+1,如果最后剩下一个就+1+2

    这样显然是假的,考虑反悔操作:

    ①+2+1->2*(+1+2),等价于用1的代价把i+1位+3

    ②+3->(+1+2)+(+2+1),等价于用1的代价把i+1位+3(前提是至少有一个+3)

    ②+3->3*(+1+2),等价于用2的代价把i+1位+6(前提是至少有一个+3)

    维护当前可以的最多+3次数,判断一下剩余情况与剩余的奇偶即可

    并不需要考虑+3具体是怎么得到的,如果要拆的话等于把之前的一系列组合操作拆开

    感受一下

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define ll long long
    #define file
    using namespace std;
    
    int n,i,j,k,l,x,X,cnt,sum;
    ll ans;
    
    int main()
    {
    	freopen("building.in","r",stdin);
    	#ifdef file
    	freopen("building.out","w",stdout);
    	#endif
    	
    	scanf("%d",&n);
    	fo(i,1,n)
    	{
    		scanf("%d",&x);x-=X;
    		if (x<=0) {X=cnt=0;continue;}
    		
    		if (cnt*3>=x)
    		X=(x%3==0)?0:(3-x%3),ans+=(x/3)+(x%3>0),cnt=(x/3)*2+(x%3==2);
    		else
    		X=((x-cnt*3)/2)+(x-cnt*3)%2*2,x-=cnt*3,ans+=cnt+(x+1)/2,cnt=cnt*2+x/2;
    	}
    	printf("%lld
    ",ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	
    	return 0;
    }
    
  • 相关阅读:
    cocos2d-x笔记5: 通过jni实现C++调用Java
    cocos2d-x笔记4: TextField不能删除内容,以及我的解决办法。。。
    C++ 11 笔记 (六) : 随机数
    C++ 11 笔记 (五) : std::thread
    C++ 11 笔记 (四) : std::bind
    C++ 11 笔记 (三) : auto
    C++ 11 笔记 (二) : for循环
    要做的题目
    【C补充】结构体的内存分配,匈牙利命名法
    【C补充】文件操作
  • 原文地址:https://www.cnblogs.com/gmh77/p/12718508.html
Copyright © 2011-2022 走看看