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;
    }
    
  • 相关阅读:
    hdu 3342 Legal or Not 拓排序
    hdu 1596 find the safest road Dijkstra
    hdu 1874 畅通工程续 Dijkstra
    poj 2676 sudoku dfs
    poj 2251 BFS
    poj Prime Path BFS
    poj 3278 BFS
    poj 2387 Dijkstra 模板
    poj 3083 DFS 和BFS
    poj 1062 昂贵的聘礼 dijkstra
  • 原文地址:https://www.cnblogs.com/gmh77/p/12718508.html
Copyright © 2011-2022 走看看