【CTSC 2007】 数据备份

【题目链接】

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

【算法】

             首先,有一个很显然的结论 : 如果要使距离和最小,必须选择相邻的办公楼配对

             问题就转化为了 : 有一个包含(n-1)个数的序列,在这(n-1)个数中选k个,相邻的数不能选,使得和最小

             考虑这个序列中最小的元素,我们发现,如果选这个数,那么与它相邻的两个数都不能选,如果不选,那么与它相邻的两个数都要选

             因此, 我们可以选出序列中最小的元素Di,将Di-1和Di+1删除,将Di-1+Di+1-Di加入,问题就转化为了在现在的序列中找到(k-1)个数,相邻的数不能选,使得和最小,这样,如果没有选Di-1+Di+1-Di这个数,说明选Di是最优策略,否则说明不是最优策略,

             答案正好将Di减去,加上了Di-1+Di+1

             那么,堆和链表是可以解决这个问题的

 【代码】

           

#include<bits/stdc++.h>
using namespace std;
#define MAXN 200010
const long long INF = 1e10;

int i,n,k;
int pre[MAXN],nxt[MAXN];
long long s[MAXN],d[MAXN];
bool visited[MAXN];
long long ans,val;

struct info
{
        long long d;
        int pos;
} 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)
                {
                        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,&k);
        for (i = 1; i <= n; i++) scanf("%lld",&s[i]);
        for (i = 1; i < n; i++) d[i] = s[i+1] - s[i];
        for (i = 1; i < n; i++)
        {
                pre[i] = i - 1;
                nxt[i] = i + 1;
                H.insert((info){d[i],i});
        }
        d[0] = d[n] = INF;
        for (i = 1; i <= k; 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;
                d[tmp.pos] = d[pre[tmp.pos]] + d[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){d[tmp.pos],tmp.pos});
        }
        printf("%lld\n",ans);
        
        return 0;
    
}

 

             

posted @ 2018-07-02 10:07  evenbao  阅读(213)  评论(0编辑  收藏  举报