您的位置:首页 > 其它

【bzoj1150】【CSTC2007】【数据备份】【贪心】

2015-09-13 08:09 309 查看

Description






Input

输入的第一行包含整数n和k,其中n(2 ≤ n ≤100 000)表示办公楼的数目,k(1≤ k≤ n/2)表示可利用的网络电缆的数目。接下来的n行每行仅包含一个整数(0≤ s ≤1000 000 000), 表示每个办公楼到大街起点处的距离。这些整数将按照从小到大的顺序依次出现。

Output

输出应由一个正整数组成,给出将2K个相异的办公楼连成k对所需的网络电缆的最小总长度。

Sample Input

5 2

1

3

4

6

12

Sample Output

4

HINT

上面的样例输入给出了前面描述的示例情形 对于每一个测试点,如果写到输出文件中的答案正确,则得到该测试点100%的分数,否则得零分。30%的输入数据满足n≤20。60%的输入数据满足n≤10 000。
题解:
观察一下发现就是种树。。
#include<iostream>
#include<cstdio>
#define p 0x7fffffff
using namespace std;
int n,m,pos[200001],h[200001],l[200001],r[200001],u;
long long a[200001],b[200001],ans;
void up(int x)
{
    while (x>1)
     {
        if (a[h[x]]<a[h[x>>1]])
         {
           swap(h[x],h[x>>1]);
           swap(pos[h[x]],pos[h[x>>1]]);
           x=x>>1;
         }
        else break;
     }
}
void down(int x)
{
   int u;
   while (x<<1<=n)
    {
       if (a[h[x<<1]]<a[h[x<<1|1]]||x<<1==n) u=x<<1;
       else u=x<<1|1;
       if (a[h[x]]>a[h[u]])
        {
            swap(h[u],h[x]);
            swap(pos[h[u]],pos[h[x]]);
            x=u;
        }
       else break;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%lld",&b[0]);
    a[0]=p;a
=p;
    for (int i=1;i<=n-1;i++)
     {
       scanf("%lld",&b[i]);
       a[i]=b[i]-b[i-1];
       l[i]=i-1;r[i]=i+1;pos[i]=h[i]=i;
       up(i);
     }
    for (int i=1;i<=m;i++)
     {
       u=h[1]; 
       ans+=a[u];a[u]=a[l[u]]+a[r[u]]-a[u];
       a[l[u]]=p;down(pos[l[u]]);
       a[r[u]]=p;down(pos[r[u]]);
       down(1);
       l[u]=l[l[u]];r[u]=r[r[u]];l[r[u]]=u;r[l[u]]=u;
     }
    cout<<ans<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: