码迷,mamicode.com
首页 > 其他好文 > 详细

【bzoj1367】[Baltic2004]sequence 可并堆

时间:2017-05-18 09:53:43      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:std   nbsp   turn   log   image   int   tps   swap   content   

题目描述

技术分享

输入

技术分享

输出

一个整数R

样例输入

7
9
4
8
20
14
15
18

样例输出

13


题解

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

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using 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 可并堆

标签:std   nbsp   turn   log   image   int   tps   swap   content   

原文地址:http://www.cnblogs.com/GXZlegend/p/6871528.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!