• [BZOJ 1058][ZJOI2007]报表统计


    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1058

    题解

      方法一:离线+离散化+线段树.

        这个方式的常数太大,会T。我在洛谷跑最后两个点TLE了,在BZOJRE了。

        具体说一下怎么做吧。首先把所有数离散化,把出现过的绝对值离散化。这样我们就能得到约n+m个数和n+m个绝对值。然后,维护两颗线段树,记录数据是否出现,并记录区间出现的最大值和最小值(因为在线段树上的点是从大到小的,假设我们添加了元素k,然后我们找它的数据排位(下标)),每添加一个元素更新MIN_SORT_GAP的答案。另一颗维护绝对值的出现和消失,需要用到删除操作。其实就是线段树模拟平衡树。

      方法二:TREAP

        直接开treap,网上有题解用multiset,但是我没用,于是就练习一下treap,在BZOJ上AC,在洛谷上T了一个点(最好的时候,一般是T最后两个点).

        开两个treap,一个维护数列出现的元素,一个维护相邻元素绝对值(有删除操作).所以我建议应该用multiset.....orz.

    代码一

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 500005;
    
    int n, m, a[maxn], bkp[maxn], d[2][maxn*4], md[2], ins[maxn][2];
    int mints[maxn*10], maxts[maxn*10], mintg[maxn*10], numg[maxn*10];
    
    void builds(int o, int L, int R)
    {
        mints[o] = maxn;
        maxts[o] = 0;
        if (L == R) return;
        builds(o<<1, L, (L+R)>>1);
        builds((o<<1)|1, ((L+R)>>1)+1, R);
    }
    
    void buildg(int o, int L, int R)
    {
        mintg[o] = 0x7fffffff;
        numg[o] = 0;
        if (L == R) return;
        buildg(o<<1, L, (L+R)>>1);
        buildg((o<<1)|1, ((L+R)>>1)+1, R);
    }
    
    int find(int x, int cur)
    {
        int l = 1, r = md[cur];
        while (l < r)
        {
            int mid = (l+r) >> 1;
            if (d[cur][mid] == x) return mid;
            if (d[cur][mid] < x) l = mid+1;
            else r = mid-1;
        }
        return l;
    }
    
    void modifys(int o, int L, int R, int p)
    {
        if (L == R)
        {
            maxts[o] = mints[o] = L;
            return;
        }
        int mid = (L+R) >> 1;
        int lc = o << 1, rc = lc+1;
        if (p <= mid) modifys(lc, L, mid, p);
        else modifys(rc, mid+1, R, p);
        maxts[o] = max(maxts[lc], maxts[rc]);
        mints[o] = min(mints[lc], mints[rc]);
    }
    
    void modifyg(int o, int L, int R, int p, int del)
    {
        if (L == R)
        {
            numg[o] += del;
            if (numg[o] == 0) mintg[o] = 0x7fffffff;
            else mintg[o] = d[1][L];
            return;
        }
        int mid = (L+R) >> 1;
        int lc = o << 1, rc = lc+1;
        if (p <= mid) modifyg(lc, L, mid, p, del);
        else modifyg(rc, mid+1, R, p, del);
        mintg[o] = min(mintg[lc], mintg[rc]);
    }
    
    int query(int o, int L, int R, int y1, int y2, int cho)
    {
        if (y1 <= L && R <= y2) return (cho?mints[o]:maxts[o]);
        int mid = (L+R) >> 1;
        int lc = o << 1, rc = lc+1;
        int _min = 0x7fffffff, _max = 0;
        if (cho == 0)
        {
            if (y1 <= mid) _max = query(lc, L, mid, y1, y2, cho);
            if (mid+1 <= y2) _max = max(_max, query(rc, mid+1, R, y1, y2, cho));
            return _max;
        }
        else
        {
            if (y1 <= mid) _min = query(lc, L, mid, y1, y2, cho);
            if (mid+1 <= y2) _min = min(_min, query(rc, mid+1, R, y1, y2, cho));
            return _min;
        }
    }
    
    void zip(int cur)
    {
        int mz = 0;
        int tmp[maxn*4];
        for (int i = 1; i <= md[cur]; ++i)
            if (i == 1 || d[cur][i] != d[cur][i-1])
                tmp[++mz] = d[cur][i];
        memcpy(d[cur], tmp, sizeof(tmp));
        md[cur] = mz;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        memcpy(d[0], a, sizeof(a));
        memcpy(bkp, a, sizeof(a));
        
        md[0] = n;
        md[1] = n-1;
        for (int i = 2; i <= n; ++i) d[1][i-1] = abs(a[i]-a[i-1]);
        for (int i = 0; i < m; ++i)
        {
            char cmd[20];
            scanf("%s", cmd);
            if (cmd[0] == 'I')
            {
                int loci, x;
                scanf("%d%d", &loci, &x);
                ins[i][0] = loci; ins[i][1] = x;
                d[0][++md[0]] = x;
                d[1][++md[1]] = abs(bkp[loci]-x);
                bkp[loci] = x;
                if (loci < n) d[1][++md[1]] = abs(a[loci+1]-x);
            }
            else if (cmd[4] == 'S') ins[i][0] = 0;
                else ins[i][0] = -1;
        }
        sort(d[0]+1, d[0]+md[0]+1);
        sort(d[1]+1, d[1]+md[1]+1);
        
        zip(0);
        d[0][0] = 0x3fffffff;
        zip(1);
        builds(1, 1, md[0]);
        buildg(1, 1, md[1]);
        int msg = 0x7fffffff;
        for (int i = 1; i <= n; ++i)
        {
            int k = find(a[i], 0);
            if (i > 1)
            {
                msg = min(msg, abs(d[0][k] - d[0][query(1, 1, md[0], 1, k, 0)]));
                msg = min(msg, abs(d[0][query(1, 1, md[0], k, md[0], 1)] - d[0][k]));
            }
            modifys(1, 1, md[0], k);
            if (i > 1)
                modifyg(1, 1, md[1], find(abs(a[i]-a[i-1]), 1), 1);
        }
        
        memcpy(bkp, a, sizeof(a));
        for (int i = 0; i < m; ++i)
            if (ins[i][0] > 0)
            {
                int loci = ins[i][0];
                int k = find(ins[i][1], 0);
                
                msg = min(msg, abs(d[0][k] - d[0][query(1, 1, md[0], 1, k, 0)]));
                msg = min(msg, abs(d[0][query(1, 1, md[0], k, md[0], 1)] - d[0][k]));
                
                modifys(1, 1, md[0], k);
                modifyg(1, 1, md[1], find(abs(ins[i][1]-a[loci]), 1), 1);
                if (loci < n)
                {
                    modifyg(1, 1, md[1], find(abs(a[loci]-bkp[loci+1]), 1), -1);
                    modifyg(1, 1, md[1], find(abs(bkp[loci+1]-ins[i][1]), 1), 1);
                }
                a[loci] = ins[i][1];
            }
            else if (ins[i][0] == 0) printf("%d
    ", msg);
                else printf("%d
    ", mintg[1]);
        return 0;
    }

    代码二

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #define INF 0x3fffffff
    
    using namespace std;
    
    const int maxn = 500005;
    
    struct Treap
    {
        struct Node
        {
            Node *ch[2];
            int r, v, cnt;
            
            Node()
            {
                *this = NULL;
            }
            
            Node(int v) : v(v)
            {
                r = rand()/10*rand();
                ch[0] = ch[1] = NULL;
                cnt = 1;
            }
            
            bool operator < (const Node &rhs) const
            {
                return r < rhs.r;
            }
            
            int cmp(int x) const
            {
                if (x == v) return -1;
                return x > v;
            }
            
        }*root;
        
        void rotate(Node *&o, int d)
        {
            Node *k = o->ch[d^1];
            o->ch[d^1] = k->ch[d];
            k->ch[d] = o;
            o = k;
        }
        
        void insert(Node *&o, int x)
        {
            if (o == NULL)
            {
                o = new Node(x);
                return;
            }
            int k = o->cmp(x);
            if (k == -1) o->cnt++;
            else
            {
                insert(o->ch[k], x);
                if (o->ch[k]->r > o->r) rotate(o, k^1);
            }
        }
        
        void remove(Node *&o, int x)
        {
            int d = o->cmp(x);
            if (d == -1)
            {
                if (o->cnt == 0 || (--o->cnt) == 0)
                {
                    if (o->ch[0] == NULL)
                        o = o->ch[1];
                    else if (o->ch[1] == NULL)
                            o = o->ch[0];
                        else
                        {
                            int d1 = o->ch[0]->r > o->ch[1]->r;
                            rotate(o, d1);
                            remove(o->ch[d1], x);
                        }
                }
                return;
            }
            remove(o->ch[d], x);
        }
        
        int finds(Node *o, int x)
        {
            if (o == NULL) return INF;
            int d = o->cmp(x);
            if (d == -1) return 0;
            if (o->ch[d] == NULL) return abs(x-o->v);
            else return min(abs(x-o->v), finds(o->ch[d], x));
        }
        
        int findmin()
        {
            Node *k = root;
            while (k->ch[0] != NULL) k = k->ch[0];
            return k->v;
        }
        
    }mins, ming;
    
    int n, m, msg, a[maxn], bkp[maxn];
    
    void read(int &x)
    {
        x = 0;
        char ch;
        while ((ch = getchar()) < '0' || ch > '9');
        while (ch >= '0' && ch <= '9') x = x*10 + ch-'0', ch = getchar();
    }
    
    int main()
    {
        read(n); read(m);
        msg = INF;
        for (int i = 1; i <= n; ++i)
        {
            read(a[i]);
            msg = min(msg, mins.finds(mins.root, a[i]));
            mins.insert(mins.root, a[i]);
            if (i > 1) ming.insert(ming.root, abs(a[i]-a[i-1]));
        }
        memcpy(bkp, a, sizeof(a));
        while (m--)
        {
            char cmd[20];
            scanf("%s", cmd);
            if (cmd[0] == 'I')
            {
                int i, k;
                read(i); read(k);
                msg = min(msg, mins.finds(mins.root, k));
                mins.insert(mins.root, k);
                if (i < n) ming.remove(ming.root, abs(bkp[i]-a[i+1]));
                ming.insert(ming.root, abs(k-bkp[i]));
                ming.insert(ming.root, abs(k-a[i+1]));
                bkp[i] = k;
            }
            else if (cmd[4] == 'S') printf("%d
    ", msg);
                else printf("%d
    ", ming.findmin());
        }
        return 0;
    }
  • 相关阅读:
    Data Load Performance Optimization
    SAPBW数据仓库增量更新(转载)
    BW数据源深入研究
    SAP BW权限
    利用HTTP协议的特性进行拒绝服务攻击的一些构思
    Python自省(反射)指南 转自http://www.cnblogs.com/huxi/archive/2011/01/02/1924317.html
    交换网络中的sniffer讨论>基于交换网络的ARP spoofing sniffer
    Windows中使用精确计时器
    HTTP POST和GET的区别
    HTTP 状态代码 错误列表
  • 原文地址:https://www.cnblogs.com/albert7xie/p/7226088.html
Copyright © 2020-2023  润新知