zoukankan      html  css  js  c++  java
  • CF545C

    给 n 棵树在一维数轴上的坐标,以及它们的⾼度。现在要你砍倒 这些树,树可以向左倒也可以向右倒,砍倒的树不能重合、当然 也不能覆盖其他的树原来的位置,现在求最⼤可以砍倒的树的数 目。 1 ≤ n ≤ 10^5 , 1 ≤ xi , hi ≤ 10^9

    思路:贪心:能往左倒就尽量往左倒,否则就往又倒,证明:

    首先对于一颗树,如果他能往左边倒下,对于后面的每一颗树没有任何影响,所以往左边倒必定是优的。

    如果不能往左边倒而是要往右边倒下,考虑代价和贡献:

    贡献:答案+1;

    代价:由于不能越过右边的第一颗树,所以最坏的结果是右边的第一颗树不能倒下,代价最多是 -1 ;

    在贪心中,只要一种贪心策略能够让答案不会变差,那么这个贪心策略就是最优秀的,而我们的贪心策略中最坏的结果是贡献和代价相抵消,所以答案必定是最优的;

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define maxn 100010
    #define ll long long
    #define IL inline
    #define clear(a) memset(a,0,sizeof a)
    
    ll n,ans;
    struct edge{
        ll id,h,lef,rig;
    }e[maxn];
    
    IL void read(ll &x){
        x=0;int f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0',ch=getchar();}x*=f;
    }
    
    int main()
    {
        read(n);
        for(int i=1;i<=n;i++)
            read(e[i].id),read(e[i].h);
        for(int i=1;i<=n;i++){
            if(i==1)e[i].lef=1e14,e[i].rig=e[i+1].id-e[i].id-1;
            else if(i==n)e[i].lef=e[i].id-e[i-1].id-1,e[i].rig=1e14;
            else e[i].lef=e[i].id-e[i-1].id-1,e[i].rig=e[i+1].id-e[i].id-1;
        }
        for(int i=1;i<=n;i++){
            if(e[i].lef>=e[i].h)
                ans++,e[i-1].rig-=e[i].h;
            else if(e[i].lef<e[i].h&&e[i].rig>=e[i].h)
                ans++,e[i+1].lef-=e[i].h;
        }
        cout<<ans<<"
    ";
        return 0;
    }
  • 相关阅读:
    汇编指令记录
    nginx源码剖析(3)nginx中的内存池
    STL中的vector
    Direct3D学习笔记
    委托的作用
    vs2010 快捷键大全
    Web Service学习笔记:什么是Web Service
    [Serializable]在C#中的作用NET 中的对象序列化
    .NET中反射机制的使用与分析
    什么时候用WebService
  • 原文地址:https://www.cnblogs.com/KGW-/p/11733941.html
Copyright © 2011-2022 走看看