BZOJ1367 [Baltic2004]sequence 堆 左偏树

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1367


题意概括

Description

Input

Output

一个整数R

题解

我被自己坑死了。
左偏树合并:
	if (a==0||b==0)
		return a+b;

这样是对的。

然而:

	if (a*b==0)
		return a+b;

这样是错的。

原因是:a*b会爆int……


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long LL;
const int N=1000005;
int n,v[N],root[N],L[N],R[N],top;
int ls[N],rs[N],npl[N],size[N],val[N];
void make_heap(int x,int v){
	ls[x]=rs[x]=npl[x]=0,val[x]=v,size[x]=1;
}
int merge(int a,int b){
	if (1LL*a*b==0)
		return a+b;
	if (val[a]<val[b])
		swap(a,b);
	rs[a]=merge(rs[a],b);
	if (npl[rs[a]]>npl[ls[a]])
		swap(rs[a],ls[a]);
	npl[a]=npl[rs[a]]+1;
	size[a]=size[ls[a]]+size[rs[a]]+1;
	return a;
}
void pop(int &x){
	x=merge(ls[x],rs[x]);
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&v[i]),v[i]-=i;
	top=0;
	for (int i=1;i<=n;i++){
		make_heap(root[++top]=i,v[i]);
		L[top]=R[top]=i;
		while (top>1&&val[root[top-1]]>val[root[top]]){
			top--;
			root[top]=merge(root[top],root[top+1]);
			R[top]=R[top+1];
			while (size[root[top]]*2>R[top]-L[top]+2)
				pop(root[top]);
		}
	}
	LL ans=0;
	for (int i=1;i<=top;i++)
		for (int j=L[i];j<=R[i];j++)
			ans+=abs(val[root[i]]-v[j]);
	printf("%lld",ans);
	return 0;
} 

  

posted @ 2017-12-14 12:38  zzd233  阅读(264)  评论(0编辑  收藏  举报