查找前驱后继 方法小结

例题:HNOI2012 营业额统计

 

题目大意:

设排完序后,x的前驱为a,后继为b,求 Σ min(x-a,b-x)

法一:双向链表 64ms 1MB

#include<cstdio>
#include<algorithm>
using namespace std;
int n,rank[40000],pos,ans;
struct node
{
    int id,w;
    int l,r;
}e[40000];
bool cmp(node p,node q)
{
    return p.w<q.w;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&e[i].w),e[i].id=i;
    sort(e+1,e+n+1,cmp);
    for(int i=1;i<=n;i++) e[i].l=i-1,e[i].r=i+1;
    e[n].r=0;e[0].w=-1e9;
    for(int i=1;i<=n;i++) rank[e[i].id]=i;
    for(int i=n;i>=1;i--)
    {
        pos=rank[i];
        if(e[pos].l&&e[pos].r) ans+=min(e[pos].w-e[e[pos].l].w,e[e[pos].r].w-e[pos].w);
        else if(e[pos].l) ans+=e[pos].w-e[e[pos].l].w;
        else if(e[pos].r) ans+=e[e[pos].r].w-e[pos].w;
        else ans+=e[pos].w;
        e[e[pos].r].l=e[pos].l;
        e[e[pos].l].r=e[pos].r;
    }
    printf("%d",ans);
}
View Code

法二:set  101ms 1MB

#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
set<int>s;
int n,x,tmp,l,r,mid,w,k;
int ans;
int main()
{
    scanf("%d",&n);
    scanf("%d",&x);
    s.insert(x);
    ans+=x; 
    for(int i=1;i<n;i++)
    {
        scanf("%d",&x);
        set<int>::iterator a=s.lower_bound(x);
        set<int>::iterator b=a;
        if(a!=s.begin()) a--;
        if(b==s.end()) b--;
        ans+=min(abs(x-*a),abs(*b-x));
        s.insert(x);
    }
    printf("%d",ans);
}
View Code

法三:splay 90ms 1004KB

#include<cstdio>
#include<algorithm>
#define N 32770
#define INF 2000000
using namespace std;
int root,ans;
class splay_tree
{
    private:
        int pre[N],ch[N][2],key[N],tot;
    public:
        inline void newnode(int &r,int fa,int k)
        {
            r=++tot;
            pre[r]=fa;
            key[r]=k;
        }
        inline void rot(int x,int kind)
        {
            int y=pre[x];
            ch[y][!kind]=ch[x][kind];
            pre[ch[x][kind]]=y;
            ch[x][kind]=y;
            if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
            pre[x]=pre[y];
            pre[y]=x;
        }
        inline void splay(int x,int goal)
        {            
            while(pre[x]!=goal)
            {
                int y=pre[x];
                int kind=ch[y][0]==x;
                if(pre[y]==goal) rot(x,kind);
                else
                {
                    kind=ch[pre[y]][0]==y;
                    if(ch[y][!kind]==x)
                    {                        
                        rot(y,kind);
                        rot(x,kind);
                    }
                    else
                    {
                        rot(x,!kind);
                        rot(x,kind);
                    }
                }
            }
            root=x;
        }
        inline int insert(int x)
        {
            int r=root;
            while(ch[r][x>key[r]]) 
            {
                if(x==key[r]) {splay(r,0);return 0;}
                r=ch[r][x>key[r]];
            }
            if(x==key[r]) {splay(r,0);return 0;}
            newnode(ch[r][x>key[r]],r,x);
            splay(ch[r][x>key[r]],0);
            return 1;
        }
        inline int get_pre(int x)
        {
            int r=ch[x][0];
            if(!r) return -INF;
            while(ch[r][1]) r=ch[r][1];
            return key[r];
        }
        inline int get_suf(int x)
        {
            int r=ch[x][1];
            if(!r) return INF;
            while(ch[r][0]) r=ch[r][0];
            return key[r];
        }
        
}tree;
int main()
{
    int n,x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(i==1)
        {
            ans+=x;
            tree.newnode(root,0,x);
        }
        else
        {
            if(!tree.insert(x)) continue;
            int a=tree.get_pre(root);
            int b=tree.get_suf(root);
            ans+=min(x-a,b-x);
        }    
    }
    printf("%d",ans);
}
View Code
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6707125.html