zoukankan      html  css  js  c++  java
  • ZOJ 3512 Financial Fraud (左偏树)

    题意:给定一个序列,求另一个不递减序列,使得Abs(bi - ai) 和最小。

    析:首先是在每个相同的区间中,中位数是最优的,然后由于要合并,和维护中位数,所以我们选用左偏树来维护,当然也可以用划分树来做。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #define debug() puts("++++");
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define freopenr freopen("in.txt", "r", stdin)
    #define freopenw freopen("out.txt", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const double inf = 0x3f3f3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 50000 + 10;
    const int mod = 1e6 + 10;
    const int dr[] = {-1, 0, 1, 0};
    const int dc[] = {0, 1, 0, -1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline int Abs(int x){ return x > 0 ? x : -x; }
    inline bool is_in(int r, int c){
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    struct Node{ int key, l, r, d, fa; };
    Node tr[maxn];
    int iroot(int i){
      if(i == -1)  return -1;
      while(tr[i].fa != -1)  i = tr[i].fa;
      return i;
    }
    
    int Merge(int rx, int ry){
      if(rx == -1)  return ry;
      if(ry == -1)  return rx;
      if(tr[rx].key < tr[ry].key)  swap(rx, ry);
      int r = Merge(tr[rx].r, ry);
      tr[rx].r = r;  tr[r].fa = rx;
      if(tr[tr[rx].l].d < tr[r].d)  swap(tr[rx].l, tr[rx].r);
      if(tr[rx].r == -1)  tr[rx].d = 0;
      else  tr[rx].d = tr[tr[rx].r].d + 1;
      return rx;
    }
    
    int del(int i){
      if(i == -1) return -1;
      int l = tr[i].l, r = tr[i].r, y = tr[i].fa, x;
      tr[i].l = tr[i].r = tr[i].fa = -1;
      tr[x = Merge(l, r)].fa = y;
      if(y != -1 && tr[y].l == i)  tr[y].l = x;
      else if(y != -1 && tr[y].r == i)  tr[y].r = x;
      for( ; y != -1; x = y, y = tr[y].fa){
        if(tr[tr[y].l].d < tr[tr[y].r].d)  swap(tr[y].l, tr[y].r);
        if(tr[y].d == tr[tr[y].r].d + 1)  break;
        tr[y].d = tr[tr[y].r].d + 1;
      }
      if(x != -1)  return iroot(x);
      return iroot(y);
    }
    
    int top(int i){ return tr[i].key; }
    int pop(int &i){
      Node out = tr[i];
      int l = tr[i].l, r = tr[i].r;
      tr[i].l = tr[i].r = tr[i].fa = -1;
      tr[l].fa = tr[r].fa = -1;
      i = Merge(l, r);
      return out.key;
    }
    
    int a[maxn];
    void init(){
      for(int i = 0; i < n; ++i){
        scanf("%d", a+i);
        tr[i].key = a[i];
        tr[i].l = tr[i].r = tr[i].fa = -1;
        tr[i].d = 0;
      }
    }
    int tree[maxn], sz[maxn], cnt[maxn];
    
    void solve(){
      int m = -1;
      for(int i = 0; i < n; ++i){
        tree[++m] = i;
        sz[m] = cnt[m] = 1;
        while(m > 0 && top(tree[m-1]) >= top(tree[m])){
          tree[m-1] = Merge(tree[m-1], tree[m]);
          sz[m-1] += sz[m];
          cnt[m-1] += cnt[m];
          --m;
          while(cnt[m] > (sz[m]+1) / 2){
            pop(tree[m]);
            --cnt[m];
          }
        }
      }
      LL ans = 0;
      int k = 0;
      for(int i = 0; i <= m; ++i){
        int t = top(tree[i]);
        for(int j = 0; j < sz[i]; ++j, ++k)
          ans += Abs(t - a[k]);
      }
      printf("%lld
    ", ans);
    }
    
    int main(){
      while(scanf("%d", &n) == 1 && n){
        init();
        solve();
      }
      return 0;
    }
    

      

  • 相关阅读:
    SPOJ SAMER08A
    SPOJ TRAFFICN
    CS Academy Set Subtraction
    CS Academy Bad Triplet
    CF Round 432 C. Five Dimensional Points
    CF Round 432 B. Arpa and an exam about geometry
    SPOJ INVCNT
    CS Academy Palindromic Tree
    身体训练
    简单瞎搞题
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/6654063.html
Copyright © 2011-2022 走看看