bzoj1150: [CTSC2007]数据备份Backup(堆+贪心)

题目传送门

解法:
跟上一题差不多一个思想。
bzoj2151
只不过这题多了一个比较恶心的边界而已。

那么相对于边界值。就拿他前面没有点来举例。
假设现在前面没有点了。那么肯定选他之后不用反悔啊。
因为你后面那个肯定比你小啊要不然干嘛选你呢。
所以说选完之后把自己和后面的点删除就行了。
维护一下即可。
跟2151唯一的不同也就这个点了。
如果后面没有点也是一样的道理。。

代码实现:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct node {
    int w,c;node() {w=c=0;}
    friend bool operator <(node n1,node n2){return n1.c>n2.c;}
};priority_queue a;
int q[110000],h[110000],n,m,s[110000];bool v[110000];
int main() {
    scanf("%d%d",&n,&m);
    scanf("%d",&s[1]);
    for(int i=2;i<=n;i++) {
        scanf("%d",&s[i]);q[i]=i-1;h[i]=i+1;
        node ss;ss.c=s[i]-s[i-1];ss.w=i;a.push(ss);
    }h[n]=-1;q[2]=-1;
    for(int i=n;i>=2;i--)s[i]-=s[i-1];s[1]=0;
    memset(v,false,sizeof(v));int ans=0;
    for(int i=1;i<=m;i++) {
        while(v[a.top().w]==true)a.pop();
        node t=a.top();a.pop();ans+=t.c;int l=q[t.w],r=h[t.w];
        node p;p.w=t.w;
        if(l!=-1&&r!=-1) {
            v[l]=true;p.c+=s[l];v[r]=true;p.c+=s[r];p.c-=t.c;
            s[t.w]=p.c;q[t.w]=q[l],h[q[l]]=t.w;h[t.w]=h[r],q[h[r]]=t.w;a.push(p);
        }
        else if(l==-1) {v[t.w]=true;v[h[t.w]]=true;q[h[h[t.w]]]=-1;}
        else {v[t.w]=true;v[q[t.w]]=true;h[q[q[t.w]]]=-1;}
    }printf("%d\n",ans);
    return 0; 
}

你可能感兴趣的:(BZOJ,杂,堆)