zoukankan      html  css  js  c++  java
  • 题解 P3620 【[APIO/CTSC 2007]数据备份】

    • UPDATE

      LeTex好象又挂了

    • 题目链接:

      https://www.luogu.org/problemnew/show/P3620
      https://www.lydsy.com/JudgeOnline/problem.php?id=1150

    • 思路(来自《算法竞赛进阶指南》):

      容易知道,最优解中配对的楼肯定是相邻的,于是我们把所有相邻楼之间的距离(D_1),(D_2),(D_3)...(D_n)记录下来,放进一个堆里。

      很明显,每次都取堆中的最小值是不正确的。那么这就有个很妙的思路:假设(D_i)是最小值,那么我们就取出(D_i),同时取出(D_{i-1})(D_{i+1}),然后再把一个一个值(D_{i+1})+(D_{i-1})-(D_i)的数放进堆,如果下一步这个新节点是最小值,很明显这是最优解。

      • 难点1:

      删了(D_{i+1}),(D_{i-1})(D_{i})后插入一个新节点,那它的前驱和后继怎么确定呢?最简单的方式当然就是用链表。

    • 难点2:

      我们要让堆和链表建立一个映射关系,怎么搞呢???我就在这里卡了好久,其实我们可以用反函数的思想。用一个数组v[]记录外面链表数组在堆中的下标,这样映射就建立了(其实这应该蛮好想的,我还是太弱了)

    • 代码:

    /*By Rye_Catcher*/
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #define ll long long 
    using namespace std;
    const int maxn=100005;
    int a[maxn],pre[maxn],ne[maxn],v[maxn];
    struct Small_Heap{
    	int heap[maxn],n;
    	inline void up(int s){
    		int fa=s>>1;
    		while(s>1){
    			if(a[heap[s]]<a[heap[fa]]){
    				swap(heap[s],heap[fa]);
    				swap(v[heap[s]],v[heap[fa]]);
    				s=fa;fa=s>>1;
    			}
    			else break;
    		}
    	}
    	inline void insert(int k){
    		heap[++n]=k;
    		v[k]=n;
    		up(n);
    	}
    	inline void down(int fa){
    		int s=fa<<1;
    		while(s<=n){
    			if(a[heap[s]]>a[heap[s+1]]&&s<n)s++;
    			if(a[heap[s]]<a[heap[fa]]){
    				swap(heap[s],heap[fa]);
    				swap(v[heap[s]],v[heap[fa]]);
    				fa=s,s=fa<<1;
    			}
    			else break;
    		}
    	}
    	inline void sub(int k){
    		heap[v[k]]=heap[n];
    		v[heap[n]]=v[k];
    		n--;
    		up(v[k]),down(v[k]);
    	}
    }poi;
    int n,k;
    template <class T>inline void read(T &x){
    	x=0;int ne=0;char c;
    	while(!isdigit(c=getchar()))ne=c=='-';
    	x=c-48;
    	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    	x=ne?-x:x;
    	return ;
    }
    int main(){
    	int la,x;
    	ll ans=0;
    	read(n),read(k);
    	read(la);
    	for(int i=2;i<=n;i++){
    		read(x);
    		a[i-1]=x-la;
    		poi.insert(i-1);
    		ne[i-1]=i,pre[i-1]=i-2;
    		la=x;
    	}
    	for(register int i=1;i<=k;i++){  
         	x=poi.heap[1];ans+=a[x];
    		if(pre[x]==0)
    		{
    			poi.sub(x),poi.sub(ne[x]);
    			pre[ne[ne[x]]]=0;
    		}
    		else if(ne[x]==n)
    		{
    			poi.sub(x),poi.sub(pre[x]);
    			ne[pre[pre[x]]]=n;
    		}
    		else {		
    		poi.sub(x);//poi.extract();   
    		poi.sub(pre[x]),poi.sub(ne[x]);
    		a[x]=a[pre[x]]+a[ne[x]]-a[x];
    		poi.insert(x);
    		pre[x]=pre[pre[x]],ne[pre[x]]=x;
    		ne[x]=ne[ne[x]],pre[ne[x]]=x;
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    hdu2328 Corporate Identity
    hdu1238 Substrings
    hdu4300 Clairewd’s message
    hdu3336 Count the string
    hdu2597 Simpsons’ Hidden Talents
    poj3080 Blue Jeans
    poj2752 Seek the Name, Seek the Fame
    poj2406 Power Strings
    hust1010 The Minimum Length
    hdu1358 Period
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/8834708.html
Copyright © 2011-2022 走看看