zoukankan      html  css  js  c++  java
  • #平衡树#洛谷 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;
    }
    
  • 相关阅读:
    P1772 [ZJOI2006]物流运输
    P3951 小凯的疑惑
    P1082 同余方程(【模板】exgcd)
    T107741 【模板】权值线段树合并
    P3205 [HNOI2010]合唱队
    P1062 数列
    P1144 最短路计数
    P1502 窗口的星星
    P4147 玉蟾宫(【模板】悬线法)
    CSP模拟赛#3 分段(T1-26)
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14979971.html
Copyright © 2011-2022 走看看