• 【题解】ZJOI2007报表统计


    洛谷传送门

    主要思路大概也是差不多的,对于两种询问分别用线段树与平衡树来维护。

    1.MIN_SORT_GAP:显然平衡树简单操作,来一发前驱、后继即可。

    2.MIN_GAP:这一个我用的是线段树:可以注意到插入元素的操作,如果是在一个元素之后反复插入,这些元素之间更新出来的最小值是不会发生改变的。只有元素与元素之间会有不断的插入而导致最小值变大。所以用线段树单点修改+维护区间min值,相邻插入值(中间不会再出现新的数字)之间可以直接暴力维护。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 99999999999LL
    #define maxn 2000000 
    #define int long long
    int n, m, tot, M1 = INF, M2 = INF, a[maxn];
    int b[maxn], root;
    struct tree
    {
        int l, r, num;  
    }T[maxn];
    
    struct node
    {
        int v, ch[2], fa;
    }P[maxn];
    
    int read()
    {
        int x = 0, k = 1;
        char c;
        c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    struct Splay_Balanced_Tree
    {
        void rotate(int x)
        {
            int f = P[x].fa, gf = P[f].fa;
            int k = x == P[f].ch[1];
            P[x].fa = gf;
            if(gf) P[gf].ch[f == P[gf].ch[1]] = x;
            P[f].ch[k] = P[x].ch[k ^ 1], P[P[x].ch[k ^ 1]].fa = f;
            P[f].fa = x, P[x].ch[k ^ 1] = f;
        }
    
        void Splay(int x, int goal)
        {
            while(P[x].fa != goal)
            {
                int f = P[x].fa, gf = P[f].fa;
                if(gf != goal) (P[f].ch[1] == x) ^ (P[gf].ch[1] == f) ? rotate(x) : rotate(f);
                rotate(x);
            }
            if(goal == 0) root = x; 
        }
    
        void ins(int x)
        {
            int u = root, ff = 0;
            while(u && P[u].v != x)
            {
                ff = u;
                u = P[u].ch[P[u].v < x];
            }
            if(!u)
            {
                u = ++ tot;
                P[u].fa = ff;
                if(ff) P[ff].ch[P[ff].v < x] = u;
                P[u].v = x;
                Splay(u, 0);
            } 
        }
    
        void Find(int x)
        {
            int u = root;
            if(!u) return;
            while(P[u].v != x && P[u].ch[P[u].v < x]) u = P[u].ch[P[u].v < x];
            Splay(u, 0);
        }
    
        int next(int x, int k)
        {
            Find(x);
            int u = root;
            if(P[u].v == x) return P[u].v;
            if((P[u].v < x && !k) || (P[u].v > x && k)) return P[u].v;
            u = P[u].ch[k];
            while(P[u].ch[k ^ 1]) u = P[u].ch[k ^ 1];
            return P[u].v;
        }
    }SBT;
    
    struct Segament_Tree
    {
        void build(int p, int l, int r)
        {
            T[p].l = l, T[p].r = r;
            if(l == r) 
            {
                T[p].num = abs(a[l] - a[l - 1]);
                return;
            }
            int mid = (l + r) >> 1;
            build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
            T[p].num = min(T[p << 1].num, T[p << 1 | 1].num);
        }
    
        void update(int p, int x, int num)
        {
            int mid = (T[p].l + T[p].r) >> 1;
            if(T[p].l == T[p].r)
            {
                T[p].num = num;
                return;
            }
            if(x <= mid) update(p << 1, x, num);
            else update(p << 1 | 1, x, num);
            T[p].num = min(T[p << 1].num, T[p << 1 | 1].num);
        }
    }SGT;
    
    signed main()
    {
        n = read(), m = read();
        SBT.ins(INF), SBT.ins(- INF);
        a[0] = a[n + 1] = INF;
        for(int i = 1; i <= n; i ++)
        {
            a[i] = read();
            if(i != 1) 
            {
                int l = SBT.next(a[i], 0), r = SBT.next(a[i], 1);
                M2 = min(M2, min(abs(l - a[i]), abs(r - a[i])));
            }
            SBT.ins(a[i]);
            b[i] = a[i];
        }
        SGT.build(1, 1, n);
        for(int i = 1; i <= m; i ++)
        {
            string s;
            cin >> s;
            if(s[0] == 'I')
            {
                int x = read(), y = read();
                int l = SBT.next(y, 0), r = SBT.next(y, 1);
                M2 = min(M2, min(abs(l - y), abs(r - y)));
                SBT.ins(y);
                M1 = min(M1, abs(b[x] - y));
                SGT.update(1, x + 1, abs(a[x + 1] - y));
                b[x] = y;
            }
            else if(s[4] == 'G') printf("%lld
    ", min(M1, T[1].num));
            else printf("%lld
    ", M2);
        }
        return 0;
    }
  • 相关阅读:
    怎样才能让您的网站看起来很专业 ?
    JavaScript slice() 方法
    Jquery日历控件
    100w数据,查询只要1秒(转)
    我的WCF之旅(1):创建一个简单的WCF程序(转载)
    名企面试官精讲典型编程题之C#篇(转自CSDN)
    day01
    Delphi初浅入门笔记之十二:多媒体编程五(绘制文字篇)
    Delphi初浅入门笔记之四:过程与函数(函数篇)
    Delphi初浅入门笔记之三:过程和函数(过程篇)
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/8451961.html
Copyright © 2020-2023  润新知