zoukankan      html  css  js  c++  java
  • [BeiJing 2017 Wc]神秘物质——Splay

    题面

       Bzoj4864

    解析

       合并序列相邻的两点,在序列中插入一个点,直接考虑Splay

      先考虑如何完成操作3, 4

      对于操作3,显然是区间最大减去区间最小,Splay维护一下即可

      对于操作4,实际上就是求区间内相邻两数的差的绝对值的最小值(注意是绝对值,我一开始就写错了), 那么每个节点还需要维护当前点与它前驱的差的绝对值,查询$[l, r]$的答案,实际上是在Splay的$[l+1, r]$节点中查询

      操作1:把x旋转至根,把x+2旋转至根的右儿子,x+1就是x+2的左儿子,直接删除。因为相邻两数的差也变了,所以先更新x+2的信息,再更新x的信息

      操作2:把x旋转至根,x+1就是它的后继,在后继的左儿子新开一个节点,存信息,相邻两数的差改变了,所以后继的信息也要更新,再把新开的节点旋转至根,完成整颗Splay的信息更新

     代码:

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 100004;
    
    template<class T> void read(T &re)
    {
        re=0;
        T sign=1;
        char tmp;
        while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1;
        re=tmp-'0';
        while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=(re<<3)+(re<<1)+(tmp-'0');
        re*=sign;
    }
    
    int n, m, root, tot;
    int a[maxn];
    
    struct splay_tree{
        int fa, s[2], siz;
        int val, mx, mn, mu, b;
    }tr[maxn<<1];
    
    void update(int x)
    {
        int ls = tr[x].s[0], rs = tr[x].s[1];
        tr[x].siz = tr[ls].siz + tr[rs].siz + 1;
        tr[x].mx = tr[x].mn = tr[x].val;
        tr[x].mu = tr[x].b;
        if(ls)
        {
            tr[x].mx = max(tr[x].mx, tr[ls].mx);
            tr[x].mn = min(tr[x].mn, tr[ls].mn);
            tr[x].mu = min(tr[x].mu, tr[ls].mu);
        }
        if(rs)
        {
            tr[x].mx = max(tr[x].mx, tr[rs].mx);
            tr[x].mn = min(tr[x].mn, tr[rs].mn);
            tr[x].mu = min(tr[x].mu, tr[rs].mu);
        }
    }
    
    void Rotate(int x)
    {
        int y = tr[x].fa, z = tr[y].fa, k = (tr[y].s[1] == x), w = (tr[z].s[1] == y), son = tr[x].s[k^1];
        tr[y].s[k] = son;tr[son].fa = y;
        tr[x].s[k^1] = y;tr[y].fa = x;
        tr[z].s[w] = x;tr[x].fa = z;
        update(y);update(x);
    }
    
    void Splay(int x, int to)
    {
        int y, z;
        while(tr[x].fa != to)
        {
            y = tr[x].fa;
            z = tr[y].fa;
            if(z != to)
                Rotate((tr[y].s[0] == x) ^ (tr[z].s[0] == y)? x: y);
            Rotate(x);
        }
        if(!to)
            root = x;
    }
    
    void build(int l, int r, int ff)
    {
        int mid = (l + r)>>1;
        if(l < mid)
            build(l, mid - 1, mid);
        if(mid < r)
            build(mid + 1, r, mid);
        if(ff)
            tr[ff].s[ff < mid] = mid;
        tr[mid].fa = ff;
        tr[mid].val = a[mid];
        tr[mid].b = abs(a[mid] - a[mid - 1]);
        update(mid);
    }
    
    int Find(int x)
    {
        int now = root;
        while(1)
        {
            int ls = tr[now].s[0], rs = tr[now].s[1];
            if(x == tr[ls].siz + 1)
                return now;
            if(x > tr[ls].siz + 1)
                x -= tr[ls].siz + 1, now = rs;
            else
                now = ls;
        }
    }
    
    int Findpre()
    {
        int now = tr[root].s[0];
        if(!now)    return 0;
        while(tr[now].s[1])     now = tr[now].s[1];
        return now;
    }
    
    int Findnxt()
    {
        int now = tr[root].s[1];
        if(!now)    return 0;
        while(tr[now].s[0])     now = tr[now].s[0];
        return now;
    }
    
    int main()
    {
        read(n);read(m);
        for(int i = 1; i <= n; ++i)
            read(a[i+1]);
        n += 2;
        build(1, n, 0);
        tr[0].s[1] = root = (1 + n)>>1;
        tot = n;
        for(int i = 1; i <= m; ++i)
        {
            char opt[8];
            scanf("%s", opt);
            if(opt[1] == 'e')
            {
                int x, e;
                read(x);read(e);
                x++;
                int now = Find(x);
                Splay(now, 0);
                int pre = Findpre();
                tr[now].b = abs(e - tr[pre].val);
                tr[now].val = e;
                int nnxt = Find(x + 2);
                Splay(nnxt, now);
                tr[nnxt].b = abs(tr[nnxt].val - e);
                tr[nnxt].s[0] = 0;
                update(nnxt);update(now);
            }
            else if(opt[0] == 'i')
            {
                int x, e;
                read(x);read(e);
                x++;
                int now = Find(x);
                Splay(now, 0);
                int nxt = Findnxt();
                tr[nxt].s[0] = ++tot;
                tr[tot].val = e;
                tr[tot].fa = nxt;
                tr[tot].b = abs(e - tr[now].val);
                tr[nxt].b = abs(tr[nxt].val - e);
                Splay(tot, 0);
            }
            else if(opt[1] =='a')
            {
                int x, y;
                read(x);read(y);
                x++;y++;
                x = Find(x - 1);
                y = Find(y + 1);
                Splay(x, 0);
                Splay(y, x);
                int now = tr[y].s[0];
                printf("%d
    ", tr[now].mx - tr[now].mn);
            }
            else
            {
                int x, y;
                read(x);read(y);
                x += 2;
                y++;
                x = Find(x - 1);
                y = Find(y + 1);
                Splay(x, 0);
                Splay(y, x);
                int now = tr[y].s[0];
                printf("%d
    ", tr[now].mu);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    JDBC的使用流程
    typescript vscode /bin/sh: ts-node: command not found
    小程序打开app场景
    设置获取cookie,setCookie,getCookie
    解决IOS微信页面回退不刷新问题
    百度小程序添加编译
    百度小程序审核不通过,基础库问题
    Charles Mac 破解安装和证书安装成功抓包单个域名是unknown
    xhrFields实现跨域访问
    Mac上启动nginx报错:nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
  • 原文地址:https://www.cnblogs.com/Joker-Yza/p/11366924.html
Copyright © 2011-2022 走看看