神秘物质
Time Limit: 10 Sec Memory Limit: 256 MB
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 的子区间。
小诚坚信这项研究可以获得诺贝尔物理学奖。为了让小诚早日了结心愿,你能否帮助他实现上述的观测和测量呢?
第一行, 两个整数 N, M, 分别表示最初的原子数目和事件总数。
第二行, N 个整数 E1, E2, …, EN, 由空格隔开。依次表示每个原子的能量。
接下来 M 行, 每行为一个字符串和两个整数, 描述一次事件,格式见题目描述。
Output
输出若干行, 按顺序依次表示每次 max 和 min 类事件的测量结果。
Sample Output
1
2
1
5
HINT
Main idea
每个点有一个权值,维护一个结构,支持合并相邻两点,删除单点,加入单点,查询区间子集极差的最大值和最小值。
Solution
首先我们可以发现,区间子集极差的最大值 显然就是整个区间的最大值-区间最小值 ,然后区间子集极差最小值 只有相邻点的才会产生贡献 。
那么我们用Splay来维护这个结构即可,维护一下子树最大值、子树最小值、子树邻差最小值 即可。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 #include <bits/stdc++.h> using namespace std;typedef long long s64;const int ONE = 300005 ;const int INF = 2147483640 ;int n,m;int x,y,a[ONE];int root,cnt;int lc[ONE],rc[ONE],fa[ONE];int size[ONE],val[ONE];int maxx[ONE],minn[ONE],del[ONE];int Ls[ONE],Rs[ONE];char ch[10 ];inline int get () { int res=1 ,Q=1 ; char c; while ( (c=getchar ())<48 || c>57 ) if (c=='-' )Q=-1 ; if (Q) res=c-48 ; while ((c=getchar ())>=48 && c<=57 ) res=res*10 +c-48 ; return res*Q; } void Up (int i) { size[i] = size[lc[i]] + size[rc[i]] + 1 ; maxx[i] = minn[i] = val[i]; del[i] = INF; Ls[i] = Rs[i] = i; if (lc[i]) { Ls[i] = Ls[lc[i]]; maxx[i] = max (maxx[i], maxx[lc[i]]); minn[i] = min (minn[i], minn[lc[i]]); del[i] = min (del[i], del[lc[i]]); del[i] = min (del[i], abs ( val[i]-val[Rs[lc[i]]] ) ); } if (rc[i]) { Rs[i] = Rs[rc[i]]; maxx[i] = max (maxx[i], maxx[rc[i]]); minn[i] = min (minn[i], minn[rc[i]]); del[i] = min (del[i], del[rc[i]]); del[i] = min (del[i], abs ( val[i]-val[Ls[rc[i]]] ) ); } } void Turn (int x) { int y = fa[x], z = fa[y]; int b = x==lc[y] ? rc[x]:lc[x]; fa[y] = x; fa[x] = z; if (b) fa[b] = y; if (z) { if (y == lc[z]) lc[z] = x; else rc[z] = x; } if (x==lc[y]) rc[x] = y,lc[y] = b; else lc[x] = y, rc[y] = b; Up (y); Up (x); } void Splay (int x,int pos) { while (fa[x] != pos) { if (fa[fa[x]] != pos) { if ( (lc[fa[x]]==x) == (lc[fa[fa[x]]]==fa[x]) ) Turn (fa[x]); else Turn (x); } Turn (x); } if (pos == 0 ) root = x; } int Build (int i,int l,int r) { int mid = l+r >> 1 ; fa[mid] = i; if (l <= mid-1 ) lc[mid] = Build (mid, l,mid-1 ); if (mid+1 <= r) rc[mid] = Build (mid, mid+1 ,r); Up (mid); return mid; } int Getid (int num) { int i = root; while (size[lc[i]] + 1 != num) { if (size[lc[i]] + 1 < num) num -= size[lc[i]] + 1 , i = rc[i]; else i = lc[i]; } return i; } void Delete (int i) { int x = Getid (i); Splay (x, 0 ); int L = Rs[lc[x]]; Splay (L,0 ); int R = Ls[rc[x]]; Splay (R,L); lc[R] = 0 ; Splay (R,0 ); } void Insert (int i,int Val) { int x = Getid (i); Splay (x,0 ); int R = Ls[rc[x]]; Splay (R,x); val[++cnt] = Val; fa[cnt] = R; lc[R] = cnt; Splay (cnt,0 ); } int main () { n=get (); m=get (); for (int i=1 ;i<=n;i++) val[i+1 ] = get (); val[1 ] = val[n+2 ] = INF; cnt = n+2 ; root = n+3 >> 1 ; Build (0 ,1 ,n+2 ); while (m--) { scanf ("%s" ,ch+1 ); x=get (); y=get (); x++; if (ch[3 ] == 'r' ) { Insert (x+1 ,y); Delete (x); Delete (x); } if (ch[3 ] == 's' ) Insert (x,y); if (ch[3 ] == 'x' ) { y++; x = Getid (x-1 ); y = Getid (y+1 ); Splay (x,0 ); Splay (y,x); printf ("%d\n" , maxx[lc[y]] - minn[lc[y]]); } if (ch[3 ] == 'n' ) { y++; x = Getid (x-1 ); y = Getid (y+1 ); Splay (x,0 ); Splay (y,x); printf ("%d\n" , del[lc[y]]); } } }