首页 > 代码库 > 【bzoj1367】[Baltic2004]sequence 可并堆

【bzoj1367】[Baltic2004]sequence 可并堆

题目描述

技术分享

输入

技术分享

输出

一个整数R

样例输入

7
9
4
8
20
14
15
18

样例输出

13


题解

可并堆,黄源河《左偏树的特点及其应用》Page 13例题原题

#include <cstdio>#include <cstring>#include <algorithm>#define N 1000010using namespace std;int a[N] , root[N] , l[N] , r[N] , d[N] , w[N] , tot , si[N] , lp[N] , rp[N];int merge(int x , int y){	if(!x) return y;	if(!y) return x;	if(w[x] < w[y]) swap(x , y);	si[x] += si[y];	r[x] = merge(r[x] , y);	if(d[l[x]] < d[r[x]]) swap(l[x] , r[x]);	d[x] = d[r[x]] + 1;	return x;}int main(){	int n , i , j , p = 0;	long long ans = 0;	scanf("%d" , &n);	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , a[i] -= i;	for(i = 1 ; i <= n ; i ++ )	{		root[++p] = ++tot , w[tot] = a[i] , si[tot] = 1 , lp[p] = rp[p] = i;		while(p > 1 && w[root[p]] < w[root[p - 1]])		{			p -- , root[p] = merge(root[p] , root[p + 1]) , rp[p] = rp[p + 1];			while(2 * si[root[p]] > rp[p] - lp[p] + 2) root[p] = merge(l[root[p]] , r[root[p]]);		}	}	for(i = 1 ; i <= p ; i ++ )		for(j = lp[i] ; j <= rp[i] ; j ++ )			ans += (long long)abs(w[root[i]] - a[j]);	printf("%lld\n" , ans);	return 0;}

 

 

【bzoj1367】[Baltic2004]sequence 可并堆