【Linked List】Data Backup

[ Question meaning ]
There are n buildings on a street, you need to connect cables for k pairs of buildings (2*k<=n), and the cost of each pair is the distance between the two buildings.
Each building can only be matched once, find the minimum cost of matching.
[Thinking]
Very clever.
Obviously, the distance difference between every two adjacent buildings is calculated at the beginning, and then k are selected.
The first thing that comes to mind should be greed. From childhood to the general election, the problem is that you cannot choose two adjacent ones.
The fundamental is that if we choose a small x, it is possible to choose the l on the left and the r on the right at the same time to obtain a better solution, so greedy cannot be used.
Then we just need to leave a chance to go back and choose l and r instead of x!
The specific method is to set val[x] as the specific value of x, after selecting x, pop it from the small top heap, delete l and r, and add a value of val[l]+val[r]-val[ The element of x], if this value is relatively small and is selected greedily later, it is equivalent to regret not choosing x and choosing l and r.
【Code】

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 110000
#define pa pair<int,int>
#define mp make_pair
#define inf 0x3f3f3f3f
using namespace std;
priority_queue< pa,vector<pa>,greater<pa> > list;
int n,m,a[MAXN],pre[MAXN],nex[MAXN];
int read()
{
    int ans=0,f=1,x;
    while(1)
    {
        x=getchar();
        if(x=='-')f=-1;
        if(x>='0'&&x<='9')break;
    }
    while(x>='0'&&x<='9')
    {
        ans=ans*10+x-'0';
        x=getchar();
    }
    return ans*f;
}
int main()
{
    n=read();m=read();

    int last=0;
    for(int i=1;i<=n;i++)
    {
        int x=read();
        a[i]=x-last;
        pre[i]=i-1;
        nex[i]=i+1;
        last=x;
    }
    pre[2]=0;
    nex[n]=0;

    for(int i=2;i<=n;i++)
        list.push(mp(a[i],i));  

    int ans=0;  
    for(int i=1;i<=m;i++)
    {

        while(list.top().first!=a[list.top().second]) list.pop();

        int val=list.top().first,x=list.top().second,l=pre[x],ll=pre[l],r=nex[x],rr=nex[r];
        ans+=val;
        list.pop();

        nex[ll]=x;

        pre[x]=ll;
        nex[x]=rr;

        pre[rr]=x;

        if(l&&r)a[x]=a[l]+a[r]-a[x];
        else a[x]=inf;
        a[l]=a[r]=inf;

        list.push(make_pair(a[x],x));
    }

    printf("%d\n",ans);

    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324663192&siteId=291194637