BZOJ 4864 [BJWC2017]神秘物质 (splay)
题目大意:
让你维护一个序列,支持:
1.合并两个相邻的数为一个新的数
2.在某个位置插入一个数
3.查询一个区间的任意子区间极差的最大值
4.查询一个区间的任意子区间极差的最小值
前两个操作可以用$splay$轻松实现
第三个操作,求区间的子区间极差最大值,额外维护子树内元素最大值最小值即可
第四个操作,求区间的子区间极差最小值
显然,我们选择的子区间越长,极差越大
所以极差最小的子区间一定是相邻的两个数构成的区间
维护一个$lb_{x},rb_{x}$,表示它前/后一个数和它差值的绝对值,每次插入/合并操作时修改这个值即可
再维护一个$ms_{x}$,表示子树内所有节点的$lb_{x},rb_{x}$最小值,注意,它不是x子树代表的区间的极差最小值,是$[L-1,R+1]$的
所以询问长度为2时需要特判
注意最大值inf不要开小了!
建议自己写个暴力和数据生成器对拍,这种题不拍简直找死
1 #include <queue> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define N1 201000 7 #define S1 (N1<<1) 8 #define T1 (N1<<2) 9 #define ll long long 10 #define uint unsigned int 11 #define rint register int 12 #define ull unsigned long long 13 #define dd double 14 #define il inline 15 #define inf 1000000000 16 using namespace std; 17 18 int gint() 19 { 20 int ret=0,fh=1;char c=getchar(); 21 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 22 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 23 return ret*fh; 24 } 25 int n,m,T; 26 int a[N1]; 27 int Abs(int x){return x>0?x:-x;} 28 struct Splay{ 29 #define root ch[0][1] 30 int ch[N1][2],fa[N1],sz[N1],mi[N1],ma[N1],tot; 31 int ms[N1],val[N1],lb[N1],rb[N1]; 32 void init(){mi[0]=ms[0]=inf;tot=n+2;} 33 int idf(int x){return ch[fa[x]][0]==x?0:1;} 34 int cre(int w){tot++,val[tot]=mi[tot]=ma[tot]=w;return tot;} 35 void con(int x,int ff,int p){fa[x]=ff,ch[ff][p]=x;} 36 void des(int x){fa[x]=ma[x]=val[x]=ch[x][0]=ch[x][1]=0,mi[x]=ms[x]=lb[x]=rb[x]=inf;} 37 void pushup(int x) 38 { 39 int ls=ch[x][0],rs=ch[x][1]; ma[x]=mi[x]=val[x]; ms[x]=min(lb[x],rb[x]); 40 if(ls) ma[x]=max(ma[x],ma[ls]), mi[x]=min(mi[x],mi[ls]), ms[x]=min(ms[x],ms[ls]); 41 if(rs) ma[x]=max(ma[x],ma[rs]), mi[x]=min(mi[x],mi[rs]), ms[x]=min(ms[x],ms[rs]); 42 sz[x]=sz[ls]+sz[rs]+1; 43 } 44 void rot(int x) 45 { 46 int y=fa[x],ff=fa[y],px=idf(x),py=idf(y); 47 fa[ch[x][px^1]]=y,ch[y][px]=ch[x][px^1]; 48 ch[x][px^1]=y,fa[y]=x,ch[ff][py]=x,fa[x]=ff; 49 pushup(y),pushup(x); 50 } 51 void splay(int x,int to) 52 { 53 to=fa[to];int y; 54 while(fa[x]!=to) 55 { 56 y=fa[x]; 57 if(fa[y]==to) rot(x); 58 else if(idf(y)==idf(x)) rot(y),rot(x); 59 else rot(x),rot(x); 60 } 61 } 62 int find(int K) 63 { 64 int x=root; 65 while(1) 66 { 67 if(K>sz[ch[x][0]]){ 68 K-=sz[ch[x][0]]; 69 if(K==1) return x; 70 K--; x=ch[x][1]; 71 }else{ 72 x=ch[x][0]; 73 } 74 } 75 } 76 int split(int l,int r) 77 { 78 int x=find(l); splay(x,root); 79 int y=find(r+2);splay(y,ch[x][1]); 80 return ch[y][0]; 81 } 82 void Merge(int K,int w) 83 { 84 int x=split(K,K+1),f=root,y=ch[f][1]; 85 val[x]=w; 86 if(ch[x][0]) des(ch[x][0]),ch[x][0]=0; 87 if(ch[x][1]) des(ch[x][1]),ch[x][1]=0; 88 rb[f]=lb[x]=Abs(w-val[f]); 89 rb[x]=lb[y]=Abs(w-val[y]); 90 pushup(x),pushup(y),pushup(f); 91 } 92 void Ins(int K,int w) 93 { 94 int x=split(K,K),y=ch[root][1],z=cre(w); 95 con(z,x,1); 96 rb[x]=lb[z]=Abs(w-val[x]); 97 rb[z]=lb[y]=Abs(w-val[y]); 98 pushup(z),pushup(x),pushup(y); 99 } 100 int Query_max(int L,int R) 101 { 102 int x=split(L,R); 103 return ma[x]-mi[x]; 104 } 105 int Query_min(int L,int R) 106 { 107 int x; 108 if(R-L<=1){ 109 x=split(L,R-1); 110 return rb[x]; 111 }else{ 112 x=split(L+1,R-1); 113 return ms[x]; 114 } 115 } 116 int Build(int *a,int l,int r,int ff) 117 { 118 if(l>r) return 0; 119 int mid=(l+r)>>1,x=mid+1; fa[x]=ff; val[x]=a[mid]; 120 lb[x]=(mid==0)?inf:Abs(a[mid]-a[mid-1]); 121 rb[x]=(mid==n+1)?inf:Abs(a[mid]-a[mid+1]); 122 ch[x][0]=Build(a,l,mid-1,x); 123 ch[x][1]=Build(a,mid+1,r,x); 124 pushup(x); return x; 125 } 126 #undef root 127 }s; 128 char str[10]; 129 130 int main() 131 { 132 //freopen("t2.in","r",stdin); 133 scanf("%d%d",&n,&m); 134 int i,x,y,z,cnt=0,de; s.init(); 135 for(i=1;i<=n;i++) a[i]=gint(); 136 a[0]=inf; a[n+1]=inf; 137 s.ch[0][1]=s.Build(a,0,n+1,0); 138 for(i=1;i<=m;i++) 139 { 140 scanf("%s",str); 141 x=gint(); y=gint(); 142 if(str[1]=='e'){ 143 s.Merge(x,y); 144 }else if(str[1]=='n'){ 145 s.Ins(x,y); 146 }else if(str[1]=='a'){ 147 /*cnt++; 148 if(cnt==957) 149 de=1;*/ 150 printf("%d\n",s.Query_max(x,y)); 151 }else{ 152 printf("%d\n",s.Query_min(x,y)); 153 } 154 } 155 return 0; 156 }