tyvj 1185 营业额统计 splay入门

第一道splay,算是学会了最最基础的splay操作。

有一点要特别注意,就是一字型旋转的时候要先旋转y再旋x,这样复杂度降低很多。。。不要写成两次都旋转x。。。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

struct Splay
{
    int key[maxn];
    int pre[maxn];
    int ch[maxn][2];
    int rt,tot;
    void newnode(int &r,int fa,int k)
    {
        r=++tot;
        key[r]=k;
        pre[r]=fa;
        ch[r][0]=ch[r][1]=0;
    }
    void rot(int x,int op)
    {
        int y=pre[x];
        ch[y][op^1]=ch[x][op];
        pre[ch[x][op]]=y;
        if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
        pre[x]=pre[y];
        ch[x][op]=y;
        pre[y]=x;
    }
    void splay(int x,int goal)
    {
        while(pre[x]!=goal){
            if(pre[pre[x]]==goal) rot(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x];
                int op=ch[pre[y]][0]==y;
                if(ch[y][op]==x) rot(x,op^1),rot(x,op);
                else rot(y,op),rot(x,op);
            }
        }
        if(goal==0) rt=x;
    }
    int insert(int k)
    {
        int u=rt;
        while(ch[u][k>key[u]]){
            if(k==key[u]){
                splay(u,0);
                return 0;
            }
            u=ch[u][k>key[u]];
        }
        newnode(ch[u][k>key[u]],u,k);
        splay(ch[u][k>key[u]],0);
        return 1;
    }
    void init()
    {
        MS0(pre);
        tot=0;
        newnode(rt,0,-INF);
        insert(INF);
    }
    int get_pre(int x)
    {
        int u=ch[x][0];
        while(ch[u][1]) u=ch[u][1];
        return key[u];
    }
    int get_next(int x)
    {
        int u=ch[x][1];
        while(ch[u][0]) u=ch[u][0];
        return key[u];
    }
};Splay tree;
int n,a[maxn];

int main()
{
    freopen("in.txt","r",stdin);
    while(cin>>n){
        tree.init();
        int ans=0;
        REP(i,1,n){
            scanf("%d",&a[i]);
            if(!tree.insert(a[i])) continue;
            int tmp=0;
            if(i==1) tmp=a[i];
            else{
                int x=tree.get_pre(tree.rt);
                int y=tree.get_next(tree.rt);
                tmp=min(abs(x-a[i]),abs(y-a[i]));
                //cout<<x<<" "<<y<<" "<<a[i]<<endl;
            }
            ans+=tmp;
        }
        cout<<ans<<endl;
    }
    return 0;
}

时间: 2025-01-04 07:15:44

tyvj 1185 营业额统计 splay入门的相关文章

BZOJ1588 HNOI2002 营业额统计 [Splay入门题]

[HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4128  Solved: 1305 Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业 额会出现一定的波动,当然一定的波动是能够接受

BZOJ 1588 营业额统计 Splay

主要操作为Splay中插入节点,查找前驱和后继节点. 1: #include <cstdio> 2: #include <iostream> 3: #include <cmath> 4: using namespace std; 5: #define MaxL 100005 6: #define INF 0x7ffffff 7: #define keyTree sp[sp[root].child[1]].child[0] 8:   9: struct SplayTree

BZOJ1588 营业额统计 splay tree

最基本的平衡树操作吧,第一次学splay的可以做一下 只需要插入,删除,旋转,求前驱,后继这5个操作吧 不喜欢用指针,用数组写的 <span style="color:#00cccc;">//HNOI2002营业额统计 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define INF 1<<30 #define

【BZOJ-1588】营业额统计 Splay

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 12485  Solved: 4508[Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其

BZOJ1588 [HNOI2002]营业额统计 splay模板

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 16189  Solved: 6482 [Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者

HNOI2002]营业额统计 Splay tree

保存模板: 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<string> 6 #include<string.h> 7 8 typedef long long ll; 9 using namespace std; 10 #define N 100005 11 #define inf 1<<

bzoj1588: [HNOI2002]营业额统计 splay瞎写

最近各种瞎写数论题,感觉需要回顾一下数据结构 写一发splay冷静一下(手速过慢,以后要多练练) 用splay是最直接的方法,但我感觉离散一波应该可以做出来(没仔细想过) 现在没有很追求代码优美,感觉得先打的对打的快O(∩_∩)O 1 #include <bits/stdc++.h> 2 #define INF 1000000000 3 using namespace std; 4 int root,N,n,x; 5 int fa[100005],c[100005][2],a[100005];

HNOI2002 营业额统计 splay

解题思路:找边上最近的值. 解题思路:splay 解题代码: 1 // File Name: poj3468.sz.cpp 2 // Author: darkdream 3 // Created Time: 2014年11月07日 星期五 08时45分48秒 4 #include<limits.h> 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #inc

1588: [HNOI2002]营业额统计 splay tree

//http://www.lydsy.com/JudgeOnline/problem.php?id=1588 //题意:每读入一个数,在前面输入的数中找到一个与该数相差最小的一个,把所有的差值绝对值加起来并输出 1 #include "bits/stdc++.h" 2 using namespace std; 3 const int maxn = 100010; 4 const int INF = 0x3f3f3f3f; 5 struct SplayTreeNode 6 { 7 int