杂题选讲 1 [APIO/CTSC 2007]数据备份 luogu紫题首祭

题目传送门
先闲扯一波,今天是2021年4月13日星期二,我是2021年2月25日开始学信息竞赛,
目前是全机房最菜,这是经过我的努力抄题解,终于抄出了自己首道luogu紫题,
算是纪念一下吧。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100006;
struct lb{				//用数组模拟链表 
	int prv,nxt,d,th;
}p[N];
struct d{				//小根堆 
	int D,tp;
}h[N];

int tot;
void up(int i)			//小根堆上调操作 
{
	while(i>1)
	{
		if(h[i].D<h[i>>1].D){
			swap(h[i],h[i>>1]);
			swap(p[h[i].tp].th,p[h[i>>1].tp].th);	//在链表中也需要调整,但只需要对换编号就行 
			i >>=1;
		}
		else return ;
	}
}

void down(int i)////		//小根堆下调操作 
{
	int ii= i << 1;		//ii为儿子 
	while(ii<=tot)
	{
		if(ii<tot&&h[ii].D>h[ii+1].D)++ii;
		if(h[ii].D<h[i].D) 	
		{
			swap(h[ii],h[i]);
			swap(p[h[ii].tp].th,p[h[i].tp].th);
			i = ii;
			ii = i << 1;
		}
		else return;
	}
}


void slb(int i)  //删链表 
{
	p[p[i].prv].nxt=p[i].nxt;
	p[p[i].nxt].prv=p[i].prv;
}

void sd(int i)					//删堆 
{
	if(i== --tot+1) return;
	swap(h[i],h[tot+1]);
	swap(p[h[i].tp].th,p[h[tot+1].tp].th);
	up(i);
	down(i);
}


int main() {
	int w,n,k,pre;
	cin>>n>>k>>pre;
	for(int i=1;i<n;i++)
	{
		cin>>w;	
		p[i].d=w-pre;
		p[i].prv=i-1;
		p[i].nxt=i+1;
		p[i].th=++tot;
		pre=w;
		h[tot].D=p[i].d;
		h[tot].tp=i;
		up(tot);
	}
	int ans=0;
	for(int i=1;i<=k;i++)						//核心代码,详见解析 
	{
		ans+=h[1].D;
		if(!p[h[1].tp].prv||p[h[1].tp].nxt==n)		//如果在最左或者最右边的情况
		{
			if(!p[h[1].tp].prv)
			{
				sd(p[p[h[1].tp].nxt].th);
				slb(p[h[1].tp].nxt);
			}
			else 
			{
				sd(p[p[h[1].tp].prv].th);
				slb(p[h[1].tp].prv);
			}
			slb(h[1].tp);
			sd(1);
			
		}
		else								//else 
			 {
				int tp0 = h[1].tp;
				h[1].D = p[p[h[1].tp].prv].d + p[p[h[1].tp].nxt].d - p[h[1].tp].d;  //神奇操作,详见下文解释将该节点 左右节点权值之和,减去该节点权值,加入堆中 
				p[h[1].tp].d = h[1].D;												//也加入链表中 
				down(1);
				sd(p[p[tp0].prv].th);								
				sd(p[p[tp0].nxt].th);
				slb(p[tp0].prv);
				slb(p[tp0].nxt);
			}
	}
	cout<<ans;
}```

思路很简单,有点贪心的思想,要选相邻两个为一组是显然的,对于权值最小的一组,要么选他,要么他左右两组都选,如果不是这样,显然要比这样差,这里不过多解释。

下面解释一下那个神奇操作,有点反悔的意思,将它左右结点权值减去自己权值存入,将它看做一组,也就是2-1=1,在选k组时,不会影响到所选的数量。
posted @ 2021-04-13 16:33  S_Curry  阅读(72)  评论(0编辑  收藏  举报