zoukankan      html  css  js  c++  java
  • 【BZOJ 2288】 生日礼物

    【题目链接】

                  https://www.lydsy.com/JudgeOnline/problem.php?id=2288

    【算法】

                先将这个序列的正负数合并起来,变成一个正负交替的序列

                如果新序列的正数个数小于等于M,那么直接输出正数的和即可

                否则,我们可以将某些正数和负数合并起来,或者不要某些正数

                将所有数按绝对值排序,放入堆中,问题就转化为了 : 在这些数中选出(Cnt - M)个数(其中Cnt为正数的个数),

                选了一个数后相邻的两个数就不能选,使得最后的和尽可能小 

                这个问题可以用CTSC2007数据备份的方法来解决,详见 : https://www.cnblogs.com/evenbao/p/9252503.html

    【代码】

               

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    const int INF = 2e9;
    
    struct info
    {
            int d,pos;
    };
    
    int i,n,m,l,r,cnt,ans,len;
    int a[MAXN],b[MAXN],val[MAXN],pre[MAXN],nxt[MAXN];
    bool visited[MAXN];
    info tmp;
    
    class Heap
    {
            private :
                    int tot;
                    info hp[MAXN];
            public :
                    inline bool cmp(info a,info b)
                    {
                            return a.d < b.d;        
                    }                
                    inline void Up(int x)
                    {
                            if (x == 1) return;
                            int fa = x >> 1;
                            if (cmp(hp[x],hp[fa])) 
                            {
                                    swap(hp[x],hp[fa]);
                                    Up(fa);
                            }
                    }
                    inline void Down(int x)
                    {
                            int son = x << 1;
                            if (son > tot) return;
                            if ((son + 1 <= tot) && cmp(hp[son+1],hp[son])) son++;
                            if (cmp(hp[son],hp[x]))
                            {
                                    swap(hp[son],hp[x]);
                                    Down(son);
                            }
                    }
                    inline void insert(info x)
                    {
                            tot++;
                            hp[tot] = x;
                            Up(tot);
                    }
                    inline void del()
                    {
                            swap(hp[1],hp[tot]);
                            tot--;
                            Down(1);
                    }
                    inline info get()
                    {
                            return hp[1];
                    }
    } H;
    
    int main() 
    {
            
            scanf("%d%d",&n,&m);
            for (i = 1; i <= n; i++) scanf("%d",&a[i]);
            while (n && a[n] <= 0) n--;
            i = 1;
            while (i <= n && a[i] <= 0) i++;
            if (i > n)
            {
                    printf("%d
    ",0);
                    return 0;
            }
            for (; i <= n; i++)
            {
                    if ((a[i] > 0 && a[i-1] > 0) || (a[i] <= 0 && a[i-1] <= 0)) b[len] += a[i];
                    else b[++len] = a[i];        
            }
            for (i = 1; i <= len; i++)
            {
                    if (b[i] > 0)    
                    {
                            ans += b[i];
                            cnt++;
                    } else b[i] = -b[i];
            }
            if (cnt <= m) 
            {
                    printf("%d
    ",ans);
                    return 0;
            }
            for (i = 1; i <= len; i++)
            {
                    pre[i] = i - 1;
                    nxt[i] = i + 1;
                    H.insert((info){b[i],i});
            }
            b[0] = b[len+1] = INF;
            for (i = m; i < cnt; i++)
            {
                    tmp = H.get();
                    while (visited[tmp.pos]) 
                    {
                            H.del();    
                            tmp = H.get();
                    }
                    ans -= tmp.d;
                    H.del();
                    visited[pre[tmp.pos]] = true;
                    visited[nxt[tmp.pos]] = true;
                    b[tmp.pos] = b[pre[tmp.pos]] + b[nxt[tmp.pos]] - tmp.d;
                    nxt[pre[pre[tmp.pos]]] = tmp.pos;
                    pre[tmp.pos] = pre[pre[tmp.pos]];
                    pre[nxt[nxt[tmp.pos]]] = tmp.pos;
                    nxt[tmp.pos] = nxt[nxt[tmp.pos]];
                    H.insert((info){b[tmp.pos],tmp.pos});
            }    
            printf("%d
    ",ans);
            
            return 0;
        
    }
  • 相关阅读:
    day54——Python 处理图片
    day53——Python 处理 Excel 数据
    day52——Python 处理附件
    day51——爬虫(一)
    大数据治理体系简谈
    redis环境的安装
    微服务体系操作日志如何记录?
    mysql数据库设计规范
    win系统下git代码批量克隆,批量更新
    java实现二维码登录功能
  • 原文地址:https://www.cnblogs.com/evenbao/p/9256797.html
Copyright © 2011-2022 走看看