zoukankan      html  css  js  c++  java
  • Luogu P1484 种树

    这道题目还是比较简单的

    首先题目的意思就让我们很轻易地想到DP

    我们设f[i][j]表示前i个坑中种j棵树的最大利益,则有:

    f[i][j]=max(f[i-1][j],f[i-2][j-1]+a[i])
    

    然而对于本题的数据范围之能得50pts

    要A掉的话还是要动一些脑子的

    我们先从小的情况开始讨论:

    • 当k=1时,我们只需要找一个最大的收益即可(当然全负就不要找了)

    • 当k=2时,我们先挑选一个最大的,若接下来最大的不是这个数两侧的数,那就区接下来最大的数即可

    • 当k=2时,当然可能会有情况是选这两个数相邻的两个数(当然也只有这种情况)。表述得清楚一些就是若第一次选了a[i],除非最优解是a[i-1]+a[i+1],否则都是上面的选法最优

    以此我们发现对于已经被选择的a[i],a[i-1],a[i+1]要么同时被选,要么同时落选

    因此我们开一个大根堆,每次取出a[i]之后把它的值累加至ans后,将a[i]的值改成a[pre[i]]+a[nxt[i]]-a[i] (这里的pre[i]表示i的前驱,nxt[i]表示i的后继,刚开始就分别是i-1,i+1)

    为什么呢,因为我们想一下,这样就给了程序一个返回的机会,此时当你选择了新的a[i]时,其实就是选择了原来的a[pre[i]]和a[nxt[i]]

    然后开一个STL堆即可水过

    CODE

    #include<cstdio>
    #include<queue>
    using namespace std;
    const int N=500005;
    struct node
    {
        int v,num;
        bool operator <(const node &s) const
        {
            return s.v>v;
        }
    };
    priority_queue <node> big;
    int a[N],pre[N],nxt[N],n,k,tot;
    bool vis[N];
    long long ans;
    inline char tc(void)
    {
        static char fl[100000],*A=fl,*B=fl;
        return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
        x=0; char ch=tc(); int flag=1;
        while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=tc(); }
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
        x*=flag;
    }
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        register int i;
        read(n); read(k); 
        for (i=1;i<=n;++i)
        read(a[i]),pre[i]=i-1,nxt[i]=i+1,big.push((node){a[i],i});
        nxt[0]=1; pre[n+1]=n;
        while (tot<k)
        {
            while (vis[big.top().num]) big.pop();
            node p=big.top(); big.pop();
            if (p.v<0) break; ++tot; ans+=p.v;
            p.v=a[p.num]=a[pre[p.num]]+a[nxt[p.num]]-a[p.num];
            vis[pre[p.num]]=vis[nxt[p.num]]=1;
            pre[p.num]=pre[pre[p.num]]; nxt[pre[p.num]]=p.num;
            nxt[p.num]=nxt[nxt[p.num]]; pre[nxt[p.num]]=p.num;
            big.push(p);
        }
        printf("%lld",ans);
        return 0;
    }
    
  • 相关阅读:
    73. Set Matrix Zeroes
    289. Game of Live
    212. Word Search II
    79. Word Search
    142. Linked List Cycle II
    141. Linked List Cycle
    287. Find the Duplicate Number
    260. Single Number III
    137. Single Number II
    Oracle EBS中有关Form的触发器的执行顺序
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9026156.html
Copyright © 2011-2022 走看看