1. 程式人生 > 其它 >#平衡樹#洛谷 1110 [ZJOI2007]報表統計

#平衡樹#洛谷 1110 [ZJOI2007]報表統計

平衡樹

題目


分析

最小值只需要開兩棵平衡樹,一棵維護所有元素,一棵維護相鄰最小值,
對於全域性最小值,對於每次插入查詢前驅後繼更新最小值即可,
相鄰最小值,對於每個原數列的數維護它的開頭和結尾是什麼數,
然後在往後插入一個數時直接先把原來的相鄰刪除再加進去,
求平衡樹的最小值即可


程式碼

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int N=500011,inf=1e9; char str[21];
const double alp=0.75; int ans,n,m,len,St[N],Ed[N],a[N];
inline signed iut(){
	rr int ans=0,f=1; rr char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans*f;
}
inline void print(int ans){
	if (ans<0) putchar('-'),ans=-ans;
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline signed min(int a,int b){return a<b?a:b;}
inline signed max(int a,int b){return a>b?a:b;} 
struct ScapeGoat_Tree{
	int siz[N<<1],son[N<<1][2],root,tot=0,fat[N<<1],w[N<<1],stac[N<<1],TOP;
	inline void BUILD(){
		tot=2,root=1;
		w[1]=-inf,siz[1]=2,son[1][1]=2,
		w[2]=inf,siz[2]=1,fat[2]=1;
	}
	inline bool balance(int x){return alp*siz[x]>=(max(siz[son[x][0]],siz[son[x][1]]));}
	inline void recycle(int x){
		if (son[x][0]) recycle(son[x][0]);
		stac[++TOP]=x;
		if (son[x][1]) recycle(son[x][1]);
	}
	inline signed build(int l,int r){
		if (l>r) return 0;
		rr int mid=(l+r)>>1,x=stac[mid];
		fat[son[x][0]=build(l,mid-1)]=x;
		fat[son[x][1]=build(mid+1,r)]=x;
		siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
		return x;
	}
	inline void rebuild(int x){
		TOP=0; recycle(x);
		rr int fa=fat[x],wh=son[fat[x]][1]==x;
		rr int now=build(1,TOP);
		fat[son[fa][wh]=now]=fa;
		if (root==x) root=now;
	}
	inline void Insert(int x){
		rr int now=root,renew=++tot;
		siz[renew]=1,w[renew]=x;
		while (1){
			++siz[now];
			rr bool wh=x>=w[now];
			if (son[now][wh]) now=son[now][wh];
			    else {fat[son[now][wh]=renew]=now; break;}
		}
		rr int UP=0;
		for (rr int i=renew;i;i=fat[i]) if (!balance(i)) UP=i;
		if (UP) rebuild(UP);
	}
	inline void Delete(int x){
		if (son[x][0]&&son[x][1]){
			rr int now=son[x][0];
			while (son[now][1]) now=son[now][1];
			w[x]=w[now],x=now;
		}
		rr int cho=son[x][0]?son[x][0]:son[x][1],wh=son[fat[x]][1]==x;
		fat[son[fat[x]][wh]=cho]=fat[x];
		for (rr int i=fat[x];i;i=fat[i]) --siz[i];
		if (x==root) root=cho;
	}
	inline signed arr(int x){
		rr int now=root;
		while (1){
			if (w[now]==x) return now;
			else now=son[now][w[now]<x];
		}
	}
	inline signed rank(int x){
		rr int now=root,ans=0;
		while (now){
			if (x>w[now]) ans+=siz[son[now][0]]+1,now=son[now][1];
			    else now=son[now][0];
		}
		return ans;
	}
	inline signed kth(int x){
		rr int now=root;
		while (1){
			if (siz[son[now][0]]==x-1) return now;
			else if (siz[son[now][0]]>=x) now=son[now][0];
			else x-=siz[son[now][0]]+1,now=son[now][1];
		}
	}
	inline signed pre(int x){
		rr int now=root,ans=-inf;
		while (now){
			if (x>w[now]) ans=max(ans,w[now]),now=son[now][1];
			    else now=son[now][0];
		}
		return ans;
	}
	inline signed suf(int x){
		rr int now=root,ans=inf;
		while (now){
			if (x<w[now]) ans=min(ans,w[now]),now=son[now][0];
			    else now=son[now][1];
		}
		return ans;
	}
}Tre[2];
inline signed Abs(int x){return x<0?-x:x;} 
signed main(){
	n=iut(),m=iut(),Tre[0].BUILD(),Tre[1].BUILD();
	for (rr int i=1;i<=n;++i) St[i]=Ed[i]=a[i]=iut();
	for (rr int i=1;i<n;++i) Tre[0].Insert(Abs(St[i+1]-St[i]));
	for (rr int i=1;i<=n;++i) Tre[1].Insert(St[i]);
	sort(a+1,a+1+n),ans=Abs(a[2]-a[1]);
	for (rr int i=3;i<=n;++i) ans=min(ans,Abs(a[i]-a[i-1]));
	for (rr int i=1;i<=m;++i){
		scanf("%s",str+1),len=strlen(str+1);
		if (len==6){
			rr int x=iut(),w=iut();
			if (x<n) Tre[0].Delete(Tre[0].arr(Abs(St[x+1]-Ed[x])));
			if (x<n) Tre[0].Insert(Abs(St[x+1]-w));
			Tre[0].Insert(Abs(w-Ed[x])),Ed[x]=w;
			rr int t1=Tre[1].suf(-inf),t2=Tre[1].pre(inf);
			if (w<t1) ans=min(ans,t1-w);
			else if (t2<w) ans=min(ans,w-t2);
			else {
				if (Tre[1].suf(w-1)==w) {ans=0; continue;}
				ans=min(ans,min(w-Tre[1].pre(w),Tre[1].suf(w)-w));
			}
			Tre[1].Insert(w);
		}else if (len==7) print(Tre[0].suf(-inf)),putchar(10);
		    else print(ans),putchar(10);
	}
	return 0;
}