BZOJ 1588 [HNOI2002] 营业额统计

直接用SPLAY的get_pre()求前驱,get_next()求后继,然后比较大小,求出总和即可。

貌似这题的输入有点问题,我一开始WA,后来去看了别人的DISCUSS,发现输入地方有点坑。

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2505
#define inf 1<<28
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define PII pair<int,int>
using namespace std;


inline void RD(int &ret) {
    char c;
    int flag = 1 ;
    do {
        c = getchar();
    } while(c < '0' || c > '9') ;
    ret = c - '0';
    while((c=getchar()) >= '0' && c <= '9')
        ret = ret * 10 + ( c - '0' );
    ret *= flag ;
}

int ch[1111111][2] , num[1111111] , fa[1111111] , data[11111111] ;
int root , tot ;

void rotate(int x ,int kind) { //kind = 0 ,左旋,kind = 1 ,右旋
    int y = fa[x] ;

    ch[y][!kind] = ch[x][kind] ;
    fa[ch[x][kind]] = y ;
    if(fa[y])ch[fa[y]][ch[fa[y]][1] == y] = x ;
    fa[x] = fa[y] ;
    ch[x][kind] = y ;
    fa[y] = x ;
}

void Splay(int x ,int s ) { //将节点x转到节点s下面
    while(fa[x] != s) {
        if(fa[fa[x]] == s)rotate(x ,ch[fa[x]][0] == x) ;
        else {
            int y = fa[x] ;
            int z = fa[y] ;
            int kind = ( ch[z][0] == y );
            if(ch[y][kind] == x) {
                rotate(x ,!kind) ;
                rotate(x , kind) ;
            } else {
                rotate(y , kind ) ;
                rotate(x , kind ) ;
            }
        }
    }
    if(s == 0)root = x ;
}
void newNode(int& x ,int k ,int father) {
    x = ++ tot ;
    ch[x][0] = ch[x][1] = 0 ;
    data[x] = k ;
    fa[x] = father ;
}

int insert(int k) {
    int r = root ;
    while(ch[r][data[r] < k]) {
        if(data[r] == k) {//避免重复插入
            Splay(r ,0 ) ;
            return 0 ;
        }
        r = ch[r][data[r] < k ] ;
    }
    newNode(ch[r][data[r] < k] , k , r ) ;
    Splay(ch[r][data[r] < k ] , 0 ) ;
    return 1 ;
}

int get_pree(int k) {
    int d = ch[k][0] ;
    if(d == 0)return -1 ;//没有前驱
    while(ch[d][1]) {
        d = ch[d][1] ;
    }
     return d ;
}

int get_next(int k) {
    int d = ch[k][1] ;
    if(d == 0)return -1 ;//没有后继
    while(ch[d][0]) {
        d = ch[d][0] ;
    }
    return d ;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("D:\\acm.txt" , "r" , stdin) ;
#endif
    int n ;
    while(cin >> n) {
        int ans = 0 ;
        int a ;
        root = tot = 0 ;
        for (int i = 1 ; i <= n ; i ++ ) {

            if(scanf("%d",&a) == EOF) a = 0 ;//这样输入才能A,直接scanf("%d",&a)就WA了,费解。
            if(i == 1) {
                ans += a ;
                newNode(root ,a, 0) ;
                continue ;
            }
            if(insert(a) == 0)continue ;
            int a1 = get_next(root) ;
            int a2 = get_pree(root) ;
            if(a1 == -1)ans += abs(a - data[a2] ) ;
            else if(a2 == -1)ans += abs(a - data[a1] ) ;
            else ans += min(abs(data[a1] - data[root]) ,abs(data[root] - data[a2]))  ;
        }
        cout << ans << endl;
    }
    return 0 ;
}


 

 

posted @ 2013-07-19 19:18  坚固66  阅读(140)  评论(0编辑  收藏  举报