· 博主是⑨
· 补充 : 蒟蒻
· 语文老师死得早
Delayyy君竟然用splay把数据水过了……Rank 1无压力……判0没天理啊> <
看了下自己程序主要耗在了离散化上...所以就想能不能不离散化什么的.
于是就试着写个动态空间的线段树.
在屏屏哥的证明下, 节点的个数是接近于 2n + nlogs - nlogn ( n 为实际元素个数, s为线段树值域 )
于是空间就是个很BT的东西……本题开了124M才水过……
但时间还是不理想 ( OJ上6s+ ), 因为实际每次新开的常数很大……哪天再想想有什么好方法吧……
动态线段树只有叶子节点有元素存在, 每次有元素冲突时 ( 叶子节点有2个元素 ), 就把该叶子节点新开左右儿子 ( 可以只开一个..视情况而定 ).
这样深度是O( logs )的...嗯.
果然不是很理想啊……就当做了个实验算了.
代码 ( 有大神能够狠狠优化的求留言= = )
#include <cstdio>
#include <cstdlib>
#include <algorithm>
char c;
#define mid ((l + r) >> 1)
#define gs ((c < '0' || c > '9') && c != '-')
int getint() { int wis = 0, p = 0; c = getchar(); while (gs) c = getchar(); if (c == '-') p = 1, c = getchar(); while (!gs) wis = wis * 10 + c - '0', c = getchar(); return p ? -wis : wis; }
const int INF = ~0U>>1;
using namespace std;
int hep[500010], wap[500010], pos[500010];
int right[5000010], left[5000010], tot[5000010], min_p[5000010], max_p[5000010], sav[5000010];
int n, m, root, sg, sgp, min_v, max_v, x, y, dima;
int v[500010], p[500010];
void up(int w)
{
int last = hep[w];
for (; (w >> 1) && wap[hep[w >> 1]] > wap[last]; w >>= 1)
pos[hep[w >> 1]] = w,
hep[w] = hep[w >> 1];
pos[last] = w; hep[w] = last;
}
void down(int w)
{
int j, last = hep[w];
for (; j = w << 1, j <= sgp && (wap[hep[j]] < wap[last] || j < sgp &&
wap[hep[j + 1]] < wap[last]); pos[hep[j]] = w, hep[w] = hep[j], w = j)
if (j < sgp && wap[hep[j]] > wap[hep[j + 1]]) ++j;
pos[last] = w;
hep[w] = last;
}
void change(int w)
{
if (w >> 1 && wap[hep[w >> 1]] > wap[hep[w]]) up(w);
else down(w);
}
void update(int k)
{
min_p[k] = min_p[left[k]] < min_p[right[k]] ? min_p[left[k]] : min_p[right[k]];
max_p[k] = max_p[right[k]] > max_p[left[k]] ? max_p[right[k]] : max_p[left[k]];
tot[k] = min(min(tot[right[k]], tot[left[k]]), min_p[right[k]] - max_p[left[k]]);
}
void addnode(int p, int l, int r, int k)
{
if (right[k] || left[k]) {
if (p <= mid) if (!left[k]) left[k] = ++sg, addnode(p, l, mid, left[k]);
else addnode(p, l, mid, left[k]);
else if (!right[k]) right[k] = ++sg, addnode(p, mid + 1, r, right[k]);
else addnode(p, mid + 1, r, right[k]);
update(k); return;
}
if (sav[k])
{
if (sav[k] == p) { tot[k] = 0; return; }
if (p <= mid && sav[k] > mid)
left[k] = ++sg, addnode(p, l, mid, left[k]),
right[k] = ++sg, addnode(sav[k], mid + 1, r, right[k]);
else
if (p > mid && sav[k] <= mid)
left[k] = ++sg, addnode(sav[k], l, mid, left[k]),
right[k] = ++sg, addnode(p, mid + 1, r, right[k]);
else
if (p > mid)
right[k] = ++sg, sav[right[k]] = sav[k], addnode(p, mid + 1, r, right[k]);
else
if (p <= mid)
left[k] = ++sg, sav[left[k]] = sav[k], addnode(p, l, mid, left[k]);
sav[k] = 0; update(k);
}
else sav[k] = p, max_p[k] = min_p[k] = p, tot[k] = INF;
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
n = getint(); m = getint(); min_v = -10000; max_v = 500000000; max_p[0] = -INF / 2; min_p[0] = INF / 2; tot[0] = tot[1] = dima = INF;
for (int i = 1; i <= n; ++i)
v[i] = p[i] = getint(); root = ++sg;
for (int i = 1; i < n; ++i) {
if (tot[1] != 0) addnode(v[i], min_v, max_v, root);
hep[++sgp] = i, wap[sgp] = abs(v[i + 1] - v[i]), pos[i] = i;
change(i);
}
if (tot[1] != 0) addnode(v[n], min_v, max_v, root);
for (int i = 1; i <= m; ++i)
{
while (c != 'I' && c != 'M') c = getchar();
if (c == 'I')
{
x = getint(), y = getint();
dima = min(dima, abs(p[x] - y)); p[x] = y;
if (dima == 0) continue; if (x == n) continue;
wap[x] = abs(v[x + 1] - p[x]); change(pos[x]);
if (tot[1] == 0) continue;
addnode(y, min_v, max_v, 1);
}
else
if (scanf("%c%c%c%c", &c, &c, &c, &c), c == 'S') printf("%d\n", tot[1]);
else printf("%d\n", min(dima, wap[hep[1]]));
}
}