您的位置:首页 > 其它

Bzoj1588--Hnoi2002营业额统计

2016-09-28 12:13 429 查看

平衡树练习

每次插入一个数判断是否重复,重复则返回0,否则选出与它差最小的数返回差的绝对值

最小差必定是左子树中最大点或右子树中最小点或其祖先,找找就可以了

代码:

#include<bits/stdc++.h>
#define MAXN 300005
#define MAXM 3005
#define INF 10000000000000LL
#define MOD 998244353
#define LL long long
using namespace std;

inline int read() {
int ret=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();}
return ret*f;
}

inline LL _abs(LL a) {return a>0?a:-a;}

int n;

struct node{
int son[2],par;LL v,r;
}x[MAXN];
struct Treap{
int L,R,root,cnt;
void init() {
L=0;R=1;root=MAXN-5;cnt=0;
x[MAXN-5].r=INF;x[MAXN-5].v=INF;
}

inline void rotate(int num,int p) {
int pa=x[num].par;
x[x[pa].par].son[x[x[pa].par].son[L]==pa?L:R]=num;
x[pa].son[p^1]=x[num].son

;if(x[num].son[p]) {x[x[num].son[p]].par=pa;} x[num].son[p]=pa;x[num].par=x[pa].par;x[pa].par=num; } int Insert(int v) { x[++cnt].v=v;x[cnt].r=rand()%MOD; int now=root,pre;LL le,ri; while(true) { if(v==x[now].v) {cnt--;return 0;} pre=v<x[now].v?L:R; if(!x[now].son[pre]) {x[now].son[pre]=cnt;x[cnt].par=now;break;} now=x[now].son[pre]; } now=cnt; while(true) { if(x[x[now].par].son[L]==now) pre=R;else pre=L; if(x[now].r>x[x[now].par].r) rotate(now,pre); else break; } le=x[now].son[L];ri=x[now].son[R]; while(x[le].son[R]) le=x[le].son[R]; while(x[ri].son[L]) ri=x[ri].son[L]; le=le?x[now].v-x[le].v:INF;ri=ri?x[ri].v-x[now].v:INF; now=x[now].par; if(le==ri&&le==INF&&now==root) return x[cnt].v; le=le<ri?le:ri; while(now) { le=le<_abs(x[now].v-x[cnt].v)?le:_abs(x[now].v-x[cnt].v); now=x[now].par; } return le; } }; int main() { srand(2333333); n=read();LL ret=0; Treap p;p.init(); for(int k,i=1;i<=n;i++) { k=read(); ret+=p.Insert(k); } printf("%lld\n",ret); return 0; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: