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 ; }