您的位置:首页 > 其它

【BZOJ - 1058续】 动态线段树

2013-03-08 14:45 281 查看
· 博主是⑨

· 补充 : 蒟蒻

· 语文老师死得早

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
, 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]]));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: