1150: [CTSC2007]数据备份Backup

来源:互联网 发布:云计算培训视频 编辑:程序博客网 时间:2024/05/18 17:04

题目链接

题目大意:一条数轴上有n个点,要求选出k对点,求这k对点的距离和的最小值

题解:首先肯定选相邻的点,这个显然
求出n-1个相邻点对间的距离,问题转化为给定一个长度为n−1的序列,要求选出k个不相邻的数(因为题目要求一个点最多只能在一条线段中)使得和最小

容易想到贪心,每次取最小,但是……
费用流能跑,但是会T

网络流的正确性基于退流操作,那么贪心也可以加一个修正操作

pre[i]nex[i]i

xxxxxx1

思想太神啦

当然,堆无法维护这个删除操作,需要一点小技巧
注意对第一个数和最后一个数处理边界

我的收获:贪心模拟网络流,堆的删除

#include <iostream>  #include <algorithm>  #include <cstring>#include <cstdio>  #include <queue>using namespace std;#define mp(x,y) make_pair(x,y)#define pii pair<int,int>#define M 100005#define INF 0x3f3f3f3fint n,m,ans;int v[M],pre[M],nex[M];priority_queue<pii,vector<pii>,greater<pii> > q;void work(){    for(int i=1;i<=m;i++)      {        while(q.top().first!=v[q.top().second]) q.pop();//线段长度与实际不符->被删除了         int x=q.top().second,l=pre[x],r=nex[x];        ans+=v[x],q.pop();        nex[pre[x]=pre[l]]=x;//删掉了l造成的影响         pre[nex[x]=nex[r]]=x;        v[x]=(l&&r)?(v[l]+v[r]-v[x]):INF;         v[l]=v[r]=INF;//被删除线段的长度改为INF         q.push(mp(v[x],x));    }    printf("%d\n",ans);  }void init(){    cin>>n>>m;    for(int x=0,y,i=1;i<=n;i++,x=y)         scanf("%d",&y),v[i]=y-x,pre[i]=i-1,nex[i]=i+1;    pre[2]=0,nex[n]=0;//处理边界为INF     for(int i=2;i<=n;i++) q.push(mp(v[i],i));//有效区间为[2.n] }int main()  {      init();    work();    return 0;  } 
原创粉丝点击