【HNOI2002】营业额统计【重做-Splay做法】

之前用sbt写了这个题现在自己开发了一套Splay的模板继续拿这道题试试手

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXINT 0x7fffffff
using namespace std;
struct splay
{
	splay *ch[2],*fa;//ch[0]为左子树ch[1]为右子树fa为父节点
	int data,cnt,size;//data节点数值cnt重复元素个数size树的大小
}*root,*no;
int ans;
int n,d;
void calc(splay *x)
{
	x->size=0;
	if (x->ch[0]) x->size+=x->ch[0]->size;
	if (x->ch[1]) x->size+=x->ch[1]->size;
	x->size+=1;
}
void rot(splay *x,bool flag)//flag=0左旋flag=1右旋 节省编程复杂度的小优化
{
	splay *y=x->fa;
	y->ch[!flag]=x->ch[flag];
    if (x->ch[flag]!=NULL) x->ch[flag]->fa=y;
	x->fa=y->fa;
	if (y->fa!=NULL)
	    if (y->fa->ch[0]==y) y->fa->ch[0]=x;
	    else y->fa->ch[1]=x;
	x->ch[flag]=y;
	y->fa=x;
	if (y==root) root=x;
}
void Splay(splay *x,splay *f)//将节点X提到节点f下 (地位与sbt Maintain()相同的操作0-0)
{
	while (x->fa!=f)
	{
		if (x->fa->fa==f)
		{
			if (x->fa->ch[0]==x) rot(x,1);
		    else rot(x,0);
		}
		else
		{
			splay *y=x->fa,*z=y->fa;
			if (z->ch[0]==y)
			    if (y->ch[0]==x)
			        rot(y,1),rot(x,1);
			    else
			        rot(x,0),rot(x,1);
			else
			    if (y->ch[0]==x)
			        rot(x,1),rot(x,0);
			    else
			        rot(y,0),rot(x,0);
		}
	}
	calc(x);
	calc(f);
}
void insert(int data)
{
	splay *n=root,*x=NULL;
	while (n!=NULL)
	{
		x=n;
		if (data>=n->data) n=n->ch[1];
		else n=n->ch[0];
	}
	n=new splay;
	n->ch[0]=n->ch[1]=NULL;
	n->size=1;
	n->data=data;
	n->cnt=1;
	n->fa=x;
	if (x==NULL) root=n;
	else
	if (data>=x->data) x->ch[1]=n;
	else x->ch[0]=n;
	if (n!=root) Splay(n,root);
}
splay* find(int data)
{
	if (root==NULL) return NULL;
	splay *x=root,*y=NULL;
	while (x!=NULL)
	{
		if (data>x->data)
		    y=x,x=x->ch[1];
		else
		if (data<x->data)
		    y=x,x=x->ch[0];
		else
		    return y;
	}
	return NULL;
}
splay* getmax()
{
	if (root==NULL) return NULL;
	splay *x=root;
	while (x->ch[1]) x=x->ch[1];
	return x;
}
splay* getmin()
{
	if (root==NULL) return NULL;
	splay *x=root;
	while (x->ch[0]) x=x->ch[0];
	return x;
}
int rank(int data)
{
	splay *x=find(data);
	Splay(x,root);
	if (root->ch[0]==x) return x->ch[0]->size+1;
	else
	return root->ch[0]->size+1+x->ch[0]->size+1;
}
splay* select(int k)
{
	splay *x=root;
	while (x)
	{
		if (k>x->ch[0]->size+1)
		{
			k-=x->ch[0]->size+1;
			x=x->ch[1];
		}
		else
		if (k<x->ch[0]->size+1)
		{
			x=x->ch[0];
		}
		else
		    return x;
	}
}
splay* pred(splay *x,splay *y,int data)
{
	if (x==NULL) return y;
	if (data==x->data) return y;
	if (data>x->data) return pred(x->ch[1],x,data);
	else return pred(x->ch[0],y,data);
}
splay* succ(splay *x,splay *y,int data)
{
	if (x==0) return y;
	if (x->data==data) return x;
	if (x->data>data) return succ(x->ch[0],x,data);
	else return succ(x->ch[1],y,data);
}
void remove(int data)
{
	splay *x=find(data);
	Splay(x,root);
	splay *t=succ(root,no,data);
	if (t!=no)
	{
		Splay(t,x);
		if (root->ch[1]==x)
		{
			root->ch[1]=t;
			t->ch[0]=x->ch[0];
		}
		else
		{
			root->ch[0]=t;
			t->ch[0]=x->ch[0];
		}
	}
	else
	{
		if (root->ch[1]==x)
		{
			root->ch[1]=t;
			t->ch[0]=x->ch[0];
		}
		else
		{
			root->ch[0]=t;
			t->ch[0]=x->ch[0];
		}
	}
}
int main()
{
	freopen("turnover.in","r",stdin);
	freopen("turnover.out","w",stdout);
	scanf("%d",&n);
	no=NULL;
	for (int i=1;i<=n;i++)
	{
		if (scanf("%d",&d)==EOF) d=0;
		splay *a=succ(root,no,d);
		splay *b=pred(root,no,d);
		int tmpa;
		int tmpb;
		if (a==no) tmpa=MAXINT;
		else tmpa=abs(d-a->data);
		if (b==no) tmpb=MAXINT;
		else tmpb=abs(d-b->data);
		if (a||b) ans+=min(tmpa,tmpb);
		else ans+=d;
		insert(d);
    }
    cout<<ans;
}
时间: 2024-12-13 10:24:29

【HNOI2002】营业额统计【重做-Splay做法】的相关文章

BZOJ 题目1588: [HNOI2002]营业额统计(Splay Tree 求前驱后继)

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 10828  Solved: 3771 [Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者

BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap

1588: [HNOI2002]营业额统计 Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题.经济管理学上定义了一种最小波动值来衡量这

[BZOJ 1588][HNOI2002]营业额统计(Splay)

Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题.经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营

【题解】 [HNOI2002]营业额统计 (Splay)

懒得复制,戳我戳我 Solution: \(Splay\)板子题,注意可以选择相等大小 Code: //It is coded by Ning_Mew on 4.10 #include<bits/stdc++.h> #define ls(x) node[x].ch[0] #define rs(x) node[x].ch[1] #define fa(x) node[x].fa #define root node[0].ch[1] using namespace std; const int ma

BZOJ1588 HNOI2002 营业额统计 [Splay入门题]

[HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4128  Solved: 1305 Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业 额会出现一定的波动,当然一定的波动是能够接受

BZOJ1588 [HNOI2002]营业额统计 splay模板

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 16189  Solved: 6482 [Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者

BZOJ 1588: [HNOI2002]营业额统计

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 14396  Solved: 5521[Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其

P2234 [HNOI2002]营业额统计 (权值线段树)

P2234 [HNOI2002]营业额统计 题目描述 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题.经济管理学上定义了一种最小波动值来衡量这种情况: 当最小波动值越大

HNOI2002营业额统计(平衡树)

标准的平衡树. 贴个splay吧 var v,l,r,fa:array[0..100000] of longint; root,x,i,n,ans:longint; procedure zig(x:longint); var y,z:longint; begin y:=fa[x];z:=fa[y]; if root=y then root:=x; l[y]:=r[x]; if r[x]<>0 then fa[r[x]]:=y; r[x]:=y; fa[y]:=x; fa[x]:=z; if z

luogu P2234 [HNOI2002]营业额统计

二次联通门 : luogu P2234 [HNOI2002]营业额统计 /* luogu P2234 [HNOI2002]营业额统计 splay 每次插入一个数 查询它的前驱与后继 有两点需要注意 1.大部分的数据有误..即输入的数据不够.. 2.判断前驱后继是否存在 3.注意判断该数是否已出现过 */ #include <cstdio> #define Max 50000 #define INF 1e8 namespace Z { inline int min (int a, int b)