• 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;
    }
  • 相关阅读:
    区分.net中的virtual new 与override
    DOM
    两个php函数
    中文字符,全角字符的正则表达式
    CSS实现居中代码大全
    xp纯净版
    A Visit to Two National Parks: Mount Rainier and Valley Forge
    8、检测浏览器和操作系统
    客户
    American History: The Reagan Years
  • 原文地址:https://www.cnblogs.com/KGW-/p/11733941.html
Copyright © 2020-2023  润新知