[HNOI2002]营业额统计 ( 洛谷P2234、bzoj1588 ) Treap版

2 篇文章 0 订阅
2 篇文章 0 订阅

https://www.lydsy.com/JudgeOnline/problem.php?id=1588

treap模板题
边读入,边求每个数的前驱和后继

上代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<iostream>
using namespace std;
struct Treap{
	int l,r;
	int cnt,dat;
	int val,siz;
}a[32800];
int n,root,tot,INF=2147483647,ans=0,b[32800];

int New(int val) {
	a[++tot].val=val;
	a[tot].cnt=a[tot].siz=1;
	a[tot].dat=rand();
	return tot;
}

void Update(int p) {
	a[p].siz=a[a[p].l].siz+a[a[p].r].siz+a[p].cnt;
}

void Build() {
	New(-INF); New(INF);
	root=1; a[1].r=2;
	Update(root);
}

void Zig(int &p) {
	int q=a[p].l;
	a[p].l=a[q].r; a[q].r=p; p=q;
	Update(a[p].r); Update(p);
}

void Zag(int &p) {
	int q=a[p].r;
	a[p].r=a[q].l; a[q].l=p; p=q;
	Update(a[p].l); Update(p);
}

void Insert(int &p,int val) {
	if(p==0) {
		p=New(val);
		return;
	}
	if(val==a[p].val) {
		a[p].cnt++;
		Update(p);
		return;
	}
	if(val<a[p].val) {
	    Insert(a[p].l,val);
	    if(a[p].dat<a[a[p].l].dat) Zig(p);
	}
	else {
	    Insert(a[p].r,val);
	    if(a[p].dat<a[a[p].r].dat) Zag(p);
	}
	Update(p);
}

int Getpre(int val) {
	int p=root,ans=1;
	while(p) {
		if(val==a[p].val) {
			if(a[p].l>0) {
				p=a[p].l;
				while(a[p].r>0) p=a[p].r;
				ans=p;
			}
			break;
		}
		if(a[p].val<val && a[p].val>a[ans].val) ans=p;
		p = val < a[p].val ? a[p].l : a[p].r;
	}
	return a[ans].val;
}

int Getnext(int val) {
	int p=root,ans=2;
	while(p) {
		if(val==a[p].val) {
			if(a[p].r>0) {
				p=a[p].r;
				while(a[p].l>0) p=a[p].l;
				ans=p;
			}
			break;
		}
		if(a[p].val>val && a[p].val<a[ans].val) ans=p;
		p = val < a[p].val ? a[p].l : a[p].r;
	}
	return a[ans].val;
}

int Get(int p,int val) {
	if(p==0) return 0;
	if(val==a[p].val) return p;
	return val < a[p].val ? Get(a[p].l,val) : Get(a[p].r,val);
}

int main()
{
	Build();
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&b[i]);
		Insert(root,b[i]);
		if(i==1) {ans+=b[i];continue;}
		if(a[Get(root,b[i])].cnt>1) continue;
		int u=Getpre(b[i]),v=Getnext(b[i]);
		if(u==-2147483647) u=-u;
		ans+=min(abs(b[i]-u),abs(b[i]-v));
	}
	printf("%d",ans);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值