• [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;
    }
  • 相关阅读:
    使用 yo 命令行向导给 SAP UI5 应用添加一个新的视图
    SAP Fiori Elements 应用的 manifest.json 文件运行时如何被解析的
    SAP UI5 标准应用的多语言支持
    微软 Excel 365 里如何设置下拉菜单和自动高亮成指定颜色
    SAP Fiori Elements 应用里的 Title 显示的内容是从哪里来的
    本地开发好的 SAP Fiori Elements 应用,如何部署到 ABAP 服务器上?
    如何在 Cypress 测试代码中屏蔽(Suppress)来自应用代码报出的错误消息
    教你一招:让集群慢节点无处可藏
    应用架构步入“无服务器”时代 Serverless技术迎来新发展
    MySQL数据库事务隔离性的实现
  • 原文地址:https://www.cnblogs.com/albert7xie/p/7226088.html
Copyright © 2020-2023  润新知