BZOJ1058:[ZJOI2007]报表统计——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1058
https://www.luogu.org/problemnew/show/P1110#sub
实现三种操作:
INSERT i k:在原数列的第i个元素后面添加一个新元素k;如果原数列的第i个元素已经添加了若干元素,则添加在这些元素的最后(见下面的例子)
MIN_GAP:查询相邻两个元素的之间差值(绝对值)的最小值
MIN_SORT_GAP:查询所有元素中最接近的两个元素的差值(绝对值)
显然这三种操作都可以splay做啊,愉快的敲了两个splay……
T!L!E!
(总觉得复杂度是对的,可能改成边插边更新(就像本代码一样)能过)
第三种操作没啥好想法,考虑第二种操作,用线段树维护差值最小值。
插入的元素对后来插这个位置的元素造成的贡献有影响,但之后将永远不会改变,于是暴力更新这个差值。
插入的元素影响了它之后位置的元素的贡献,且会不断改变,于是在线段树更新这个差值即可。
#include<cstdio> #include<queue> #include<cctype> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int N=1000010; const int INF=1e9; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } char s[101]; int fa[N],tr[N][2],key[N],id[N]; int b[N],del[N],c[N]; int root,sz; inline bool get(int x){ return tr[fa[x]][1]==x; } int pre(){ int now=tr[root][0]; while(tr[now][1])now=tr[now][1]; return now; } int nxt(){ int now=tr[root][1]; while(tr[now][0])now=tr[now][0]; return now; } inline void rotate(int x){ int y=fa[x],z=fa[y],which=get(x); tr[y][which]=tr[x][which^1];fa[tr[y][which]]=y; fa[y]=x;tr[x][which^1]=y;fa[x]=z; if(z)tr[z][tr[z][1]==y]=x; return; } inline void splay(int x){ int f=fa[x]; while(f){ if(fa[f])rotate(get(x)==get(f)?f:x); rotate(x);f=fa[x]; } root=x; return; } inline void insert(int v){ if(!root){ sz++;tr[sz][0]=tr[sz][1]=fa[sz]=0; key[sz]=v;root=sz; return; } int now=root,f=0; while(233){ f=now; now=tr[now][key[now]<=v]; if(!now){ sz++;tr[sz][0]=tr[sz][1]=0; fa[sz]=f;key[sz]=v; tr[f][key[f]<=v]=sz; splay(sz); break; } } return; } void build(int a,int l,int r){ if(l==r){ del[a]=abs(b[l]-b[l-1]); return; } int mid=(l+r)>>1; build(a*2,l,mid);build(a*2+1,mid+1,r); del[a]=min(del[a*2],del[a*2+1]); } void ins(int a,int l,int r,int p,int x){ if(l==r){ del[a]=x; return; } int mid=(l+r)>>1; if(p<=mid)ins(a*2,l,mid,p,x); else ins(a*2+1,mid+1,r,p,x); del[a]=min(del[a*2],del[a*2+1]); } int main(){ int n=read(),m=read(); int ans1=INF,ans2=INF; b[0]=c[0]=INF; for(int i=1;i<=n;i++){ b[i]=c[i]=read(); insert(b[i]); if(i!=1){ int pr=pre(),nx=nxt(); if(pr)ans2=min(ans2,abs(key[pr]-b[i])); if(nx)ans2=min(ans2,abs(key[nx]-b[i])); } } build(1,1,n); for(int i=1;i<=m;i++){ scanf("%s",s); if(s[0]=='I'){ int pos=read(),v=read(); insert(v); int pr=pre(),nx=nxt(); if(pr)ans2=min(ans2,abs(key[pr]-v)); if(nx)ans2=min(ans2,abs(key[nx]-v)); ans1=min(ans1,abs(c[pos]-v)); c[pos]=v; if(pos+1<=n)ins(1,1,n,pos+1,abs(b[pos+1]-v)); }else if(strlen(s)==7){ printf("%d\n",min(del[1],ans1)); }else{ printf("%d\n",ans2); } } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++