zoukankan      html  css  js  c++  java
  • bzoj 1588 [HNOI2002] 营业额统计 链表和Splay

    来自HNOI 2002营业额的统计一题,这题以前是用链表水过的,最近看见许多splay的题,赶紧张一下知识。

    题目大意就是对于一个序列,输出每个元素与它之前元素的差的最小值的和。先说链表的方法吧。

    大概就是sort一下,记录每个点的rank。然后链表一下,很好理解,复杂度nlogn,瓶颈在于排序。

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    struct node
    {
        int l,r,val,pos;
        bool operator <(node b)
        {
            return val<b.val;
        }
    }a[40000];
    int rank[40000];
    int main()
    {
        int n;
        cin>>n;
           for(int i=1;i<=n;++i)
           {
               scanf("%d",&a[i].val);a[i].pos=i;
        }
        sort(a+1,a+1+n);
        for(int i=1;i<=n;++i)
        {
               a[i].l=i-1;a[i].r=i+1;
               rank[a[i].pos]=i;
        }
        a[n].r=0;
        int ans=a[rank[1]].val;
        for(int i=n;i>1;--i)
        {
            int x=rank[i];
            if(a[x].l&&a[x].r)
            {
                ans+=min(abs(a[x].val-a[a[x].r].val),abs(a[x].val-a[a[x].l].val));
                a[a[x].r].l=a[x].l;a[a[x].l].r=a[x].r;
            }
            else if(a[x].l)
            {
                ans+=abs(a[x].val-a[a[x].l].val);
                a[a[x].l].r=a[x].r;
            }
            else
            {
                ans+=abs(a[x].val-a[a[x].r].val);
                a[a[x].r].l=a[x].l;
            }
        }
        cout<<ans<<endl; 
    }
     

    接下来是Splay啦!

    先上代码

    #include<bits/stdc++.h>
    using namespace std;
    struct tree
    {
        int l,r,w,fa;
    }t[40000];
    bool flag;
    int cnt,root;
    inline void read(int &x)
    {
        x=0;int p=1; char ch;ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-') p=-p; ch=getchar();}
        while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
        x=x*p;
    }
    inline void build(int x,int pos)
    {
        if(x==t[pos].w) {flag=1;return;} 
        if(x<t[pos].w) 
        {
            if(!t[pos].l) 
            {t[pos].l=++cnt;t[cnt].w=x;t[cnt].fa=pos;return;}
            build(x,t[pos].l);
        }
        else
        {
            if(!t[pos].r)
            {t[pos].r=++cnt;t[cnt].w=x;t[cnt].fa=pos;return;}
            build(x,t[pos].r);
        }
    }
    inline void rotate(int x,int &k)
    {
        int y=t[x].fa,z=t[y].fa;
        if(y==k) k=x;
        else
        {
            if(t[z].l==y) t[z].l=x;
            else t[z].r=x;
        }
        if(t[y].l==x) t[t[x].r].fa=y,t[y].l=t[x].r,t[x].r=y;
        else t[t[x].l].fa=y,t[y].r=t[x].l,t[x].l=y;
        t[y].fa=x;t[x].fa=z;
    }
    inline void splay(int x,int &k)
    {
        while(x!=k)
        {
            int y=t[x].fa,z=t[y].fa;
            if(y!=k)
            {
                if((t[z].l==y)^(t[y].l==x)) rotate(x,k);
                else rotate(y,k); 
            }
            rotate(x,k);
        }
    }
    inline int queryl(int x)
    {
        x=t[x].l;if(!x) return x;
        while(t[x].r) x=t[x].r;
        return x;
    }
    inline int queryr(int x)
    {
        x=t[x].r;if(!x) return x;
        while(t[x].l) x=t[x].l;
        return x;
    }
    inline int insert(int x)
    {
        flag=0;
        build(x,root);
        if(flag) return 0;
        splay(cnt,root);
        int l=queryl(cnt),r=queryr(cnt);
        int ans=1e9;
        if(l) ans=min(ans,abs(t[l].w-x));
        if(r) ans=min(ans,abs(t[r].w-x));
        return ans;
    }
    int main()
    {
        int n,x;
        read(n);
        int ans=0;
        read(x);
        ans=x;
        ++cnt;t[cnt].w=x;root=cnt;
        for(int i=1;i<n;++i)
        {
            read(x);
            ans+=insert(x);
        }
        printf("%d",ans);
    }

    这里用splay维护bst,这样每次可以查询一个元素的前驱和后继,做减法取个min即可。这时我们就需要splay操作了。splay的核心操作就是旋转,这里可以参考墩爷爷的博客,他介绍的非常详细。http://blog.csdn.net/skydec/article/details/20151805

    插入一个元素,把他rotate到根的位置,这样可以保证平均复杂度是nlogn的(虽然我不会证明),然后进行简单的bst遍历即可。rotate操作每次可以左旋或右旋一个节点,每次rotate需要改变父亲与儿子的从属关系,这个操作与树的形态有关系,有两种情况:一种是一条链的情况,一种就相反。强烈建议去墩爷爷的博客去看一下,我实在是懒得写了。但是splay常数实在是大,bzoj上比链表那个慢了1s+,在luogu上t了一个点=。=数据结构代码量大,还不好调试。但是学长说的好啊,多学数据结构可以弥补智商的不足=。=

  • 相关阅读:
    A naive AI for TicTacToe
    table font size LaTex
    Python:关于爬虫(2)
    Python:关于爬虫(1)
    RStudio的安装
    Python中安装numpy matplotlib scipy
    python函数编程
    JavaScript的基础语法
    数据结构——线性表的顺序表示(5)
    数据结构——线性表的顺序表示(4)
  • 原文地址:https://www.cnblogs.com/Elfish/p/7563507.html
Copyright © 2011-2022 走看看