【BZOJ4864】【BJWC2017】神秘物质 - Splay
题意:
Description
21ZZ 年,冬。小诚退休以后, 不知为何重新燃起了对物理学的兴趣。 他从研究所借了些实验仪器,整天研究各种微观粒子。这一天, 小诚刚从研究所得到了一块奇异的陨石样本, 便迫不及待地开始观测。 在精密仪器的视野下,构成陨石的每个原子都无比清晰。 小诚发现, 这些原子排成若干列, 每一列的结构具有高度相似性。于是,他决定对单独一列原子进行测量和测试。被选中的这列共有 N 个顺序排列的原子。 最初, 第 i 个原子具有能量 Ei。 随着时间推移和人为测试, 这列原子在观测上会产生两种变化:
merge x e 当前第 x 个原子和第 x+1 个原子合并,得到能量为 e 的新原子;
insert x e 在当前第 x 个原子和第 x+1 个原子之间插入一个能量为 e 的新原子。
对于一列原子,小诚关心的是相邻一段中能量最大和能量最小的两个原子的能量差值,
称为区间极差。 因此, 除了观测变化外,小诚还要经常统计这列原子的两类数据:
max x y 当前第 x 到第 y 个原子之间的任意子区间中区间极差的最大值;
min x y 当前第 x 到第 y 个原子之间的任意子区间中区间极差的最小值。
其中, 子区间指的是长度至少是 2 的子区间。
小诚坚信这项研究可以获得诺贝尔物理学奖。为了让小诚早日了结心愿,你能否帮助他实现上述的观测和测量呢?
Input
Output
输出若干行, 按顺序依次表示每次 max 和 min 类事件的测量结果。
题解:
看到merge和insert操作肯定是splay维护啦……
考虑如何处理询问,极差最大值肯定是区间最大值减最小值,这个不用说;
极差最小值呢?
结论是极差最小值一定是两个相邻的数之差;
考虑三个数,肯定选中间的数和与其差较小的另一个数极差最小,三个数都选不会优于这个选择,类似归纳即可;
那么splay维护子树最大/最小值,前驱后继和子树内最小极差,pushup的时候搞搞即可。
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 1000000007
8 #define eps 1e-9
9 using namespace std;
10 typedef long long ll;
11 typedef double db;
12 struct node{
13 int son[2],fa,v,l,r,siz,mi,mx,mm;
14 }t[200001];
15 int n,m,x,y,rt,cnt,num[200001];
16 char op[10];
17 bool Son(int u){
18 return t[t[u].fa].son[1]==u;
19 }
20 void pushup(int u){
21 t[u].l=t[u].son[0]?t[t[u].son[0]].l:u;
22 t[u].r=t[u].son[1]?t[t[u].son[1]].r:u;
23 t[u].siz=t[t[u].son[0]].siz+t[t[u].son[1]].siz+1;
24 t[u].mx=max(t[u].v,max(t[t[u].son[0]].mx,t[t[u].son[1]].mx));
25 t[u].mi=min(t[u].v,min(t[t[u].son[0]].mi,t[t[u].son[1]].mi));
26 t[u].mm=min(min(t[t[u].son[0]].mm,t[t[u].son[1]].mm),min(t[u].son[0]?abs(t[u].v-t[t[t[u].son[0]].r].v):inf,t[u].son[1]?abs(t[u].v-t[t[t[u].son[1]].l].v):inf));
27 }
28 int build(int l,int r,int ff){
29 int mid=(l+r)/2;
30 t[mid].fa=ff;
31 if(l<mid)t[mid].son[0]=build(l,mid-1,mid);
32 if(mid<r)t[mid].son[1]=build(mid+1,r,mid);
33 pushup(mid);
34 return mid;
35 }
36 void rotate(int u){
37 int f=t[u].fa,ff=t[f].fa,ch=Son(u),cf=Son(f);
38 t[f].son[ch]=t[u].son[ch^1];
39 t[t[f].son[ch]].fa=f;
40 t[ff].son[cf]=u;
41 t[u].son[ch^1]=f;
42 t[u].fa=ff;
43 t[f].fa=u;
44 pushup(f);
45 pushup(u);
46 }
47 void splay(int u,int to){
48 for(;t[u].fa!=to;rotate(u)){
49 int f=t[u].fa;
50 if(t[f].fa!=to)rotate(Son(u)^Son(f)?u:f);
51 }
52 if(!to)rt=u;
53 }
54 int findx(int u,int k){
55 int nw=u;
56 for(;;){
57 if(t[t[nw].son[0]].siz+1==k)return nw;
58 if(k<=t[t[nw].son[0]].siz){
59 nw=t[nw].son[0];
60 }else{
61 k-=t[t[nw].son[0]].siz+1;
62 nw=t[nw].son[1];
63 }
64 }
65 }
66 int split(int x,int y){
67 int l=findx(rt,x-1),r=findx(rt,y+1);
68 //printf("%d %d\n",l,r);
69 splay(l,0);
70 splay(r,rt);
71 return t[t[rt].son[1]].son[0];
72 }
73 void merge(int x,int y){
74 int u=split(x+1,x+2);
75 t[u].v=y;
76 t[u].son[0]=t[u].son[1]=0;
77 pushup(u);
78 pushup(t[rt].son[1]);
79 pushup(rt);
80 }
81 void ins(int x,int y){
82 int u=split(x+2,x+1);
83 t[t[rt].son[1]].son[0]=++cnt;
84 t[cnt].fa=t[rt].son[1];
85 t[cnt].v=y;
86 pushup(cnt);
87 pushup(t[rt].son[1]);
88 pushup(rt);
89 }
90 int getmx(int x,int y){
91 int u=split(x+1,y+1);
92 return t[u].mx-t[u].mi;
93 }
94 int getmi(int x,int y){
95 int u=split(x+1,y+1);
96 return t[u].mm;
97 }
98 int main(){
99 scanf("%d%d",&n,&m);
100 cnt=n+2;
101 for(int i=1;i<=n;i++){
102 scanf("%d",&t[i+1].v);
103 }
104 t[0].mx=0;
105 t[0].mi=t[0].mm=inf;
106 cnt=n+2;
107 rt=build(1,n+2,0);
108 for(int i=1;i<=m;i++){
109 scanf("%s%d%d",op,&x,&y);
110 if(op[1]=='e'){
111 merge(x,y);
112 }else if(op[1]=='n'){
113 ins(x,y);
114 }else if(op[1]=='a'){
115 printf("%d\n",getmx(x,y));
116 }else{
117 printf("%d\n",getmi(x,y));
118 }
119 }
120 return 0;
121 }