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 }

 

posted @ 2018-12-22 11:06  guapisolo  阅读(269)  评论(0编辑  收藏  举报