【BZOJ - 1058续】 动态线段树

来源:互联网 发布:unity3d 动画播放次数 编辑:程序博客网 时间:2024/06/02 05:59

    · 博主是⑨

    · 补充 : 蒟蒻

    · 语文老师死得早



    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]]));       }            }