APIO2007 数据备份 贪心+堆实现

来源:互联网 发布:淘宝改版中国质造 编辑:程序博客网 时间:2024/06/12 01:40

【算法分析】

n,k都有10^5,所以考虑贪心算法

最基本的贪心就是任意一对数必须是相邻的,这是显然的。

考虑到一重要结论:

假设现在有三条相邻的线段a1,a2,a3;a1>a2,a3>a2,如果a2小于等于最优解集中的最大元素,并且最优解集中不存在a2,则必同时存在a1,a3。

证明:如果最优解中只有a1或只有a3,那我可以把它换成a2,这组解仍然满足要求,但总距离更小。如果最优解中不存在a1或a3,那我可以用a2换掉解集中的最大元素。由于上述两种情况都不可能,所以题设成立。

 换句话说,如果我们用贪心算法,就一定会先选到a2,这时候a1和a3就可以和为整体了,因为它们要么共同被选,要么共同不被选。如果a1和a3被选中了,那么费用就增加了a1+a3-a2;

但要注意,当线段在两端时就不满足了,因此,需要在两端加两个距离无穷大的哨兵。

利用这一点我们就可以构造一个增量算法:

每次选取一个最小的线段,然后把这条线段左右的两条线段合并在一起,新线段的权值为左右之和减去中间。

每一次操作之后,都会使解集中增加一条线段,而总费用增长了一个最小值。

【教训】

写del()函数的时候忘了将swap(pos[h[x]],pos[h[r]])写进去了。wa了很久

以后还是写一个change函数算了。

【代码】

#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <algorithm>using namespace std;const int N=100005,INF=1<<30;int a[N],b[N],pos[N],L[N],R[N],h[N];int r;void up(int x){    int i=x,j;    while (i>1)    {        j=i>>1;        if (b[h[j]]>b[h[i]])        {            swap(h[i],h[j]);            swap(pos[h[i]],pos[h[j]]);            i=j;        }        else break;    }}void down(int x){    int i=x,j;    while (i*2<=r)    {        j=i*2;        if (j+1<=r && b[h[j]]>b[h[j+1]]) j++;        if (b[h[i]]>b[h[j]])        {            swap(h[i],h[j]);            swap(pos[h[i]],pos[h[j]]);            i=j;        }        else break;    }}void ins(int i){    h[++r]=i;    pos[i]=r;    up(r);}void del(int x){    swap(h[x],h[r]);    swap(pos[h[x]],pos[h[r]]);    r--;    up(x);    down(x);}int main(){    int i,k,n,ans,l,r,mid;    freopen("14.in","r",stdin);    scanf("%d%d",&n,&k);    for (i=1;i<=n;i++)        scanf("%d",&a[i]);    for (i=2;i<=n;i++)    {        b[i]=a[i]-a[i-1];        ins(i);    }    b[1]=b[n+1]=INF;    ins(1);ins(n+1);    for (i=1;i<=n+1;i++)        L[i]=i-1,R[i]=i+1;    ans=0;    while (k--)    {        mid=h[1];        ans+=b[mid];        l=L[mid];        r=R[mid];        L[R[r]]=l;        R[l]=R[r];        del(pos[mid]);        del(pos[r]);        b[l]=b[l]+b[r]-b[mid];        up(pos[l]);        down(pos[l]);    }    printf("%d\n",ans);}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 cad文字输入不了怎么办 word打不了汉字怎么办 电脑浏览器卡顿怎么办 文档里输入不了怎么办 淘宝退款卖家不处理怎么办 抵押合同丢了怎么办 抵押合同丢失了怎么办 发票货物名称多怎么办 发票上少打一个字怎么办 发票名称带星号怎么办 小贷太多还不上怎么办 生日当天买保险怎么办 我挪用公司货款怎么办 车辆改名字保险怎么办 工伤报案周六日怎么办 五菱宏光s1门下沉怎么办 新手机版本更新怎么办 戴尔电脑开机黑屏怎么办 淘宝退货不发货怎么办 铝被酸腐蚀怎么办 新娘头饰氧化了怎么办 合金饰品变黑了怎么办 麻醉机fico2升高怎么办 快递被恶意投诉怎么办 顺风快递收件人拒收怎么办 手机联系人没了怎么办 收件人号码错了怎么办 收件人写错了怎么办 快递联系不到收件人怎么办 小孩烫伤有水泡怎么办 被烫伤的疤痕怎么办 微店别人下单后怎么办 月经超了七天怎么办 收件人不在指定地址怎么办 2017款宝来熄火后异响怎么办 我身高一八米怎么办呀 规格型号错了发票怎么办 合同签错了怎么办 柜子背板起泡怎么办啊 显卡红灯不亮怎么办 小米设置全英文怎么办