WC2019 模擬 立體幾何題

好象這是liu_runda出的HEOI模擬賽來的. 感覺作爲模擬WC還是簡單了些.

Description

給一個底面爲\(n \times n\)的, 單位立方體堆疊成的幾何體的主視圖和側視圖.

在沒有俯視圖的情況下, 計算最多可以有多少個立方體.

\(n \le x10^5\).

Solution

思路還是很自然的, 就一路從暴力到正解.

先想暴力, 發現一個\((i,j)\)的位置就是\(\min{(a_i, b_j)}\). 就可以\(n^2\)了.

然後發現不修改的話可以排序後二分.

然後發現修改一邊也可以排序後二分.

然後發現都修改可以平衡樹上二分.

做完啦.

/*
@Date   : 2019-01-16 08:30:00
@Author : Curtis Nishikino ([email protected])
@Link   : https://nishikinocurtis.github.io
*/

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cctype>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> pii;

inline int rd() {
  register int x = 0, f = 0, c = getchar();
  while (!isdigit(c)) {
    if (c == '-') f = 1;
    c = getchar();
  }
  while (isdigit(c)) x = x * 10 + (c ^ 48), c = getchar();
  return f ? -x : x;
}

const int maxn = 2e+5 + 5;

int n, m, a[maxn], b[maxn];
ll ans;

struct Treap {
  struct node {
    int ch[2], v, siz, k, w;
    ll sum;
    node() {
      ch[1] = ch[0] = 0;
      v = w = siz = k = 0;
    }
  }t[maxn];
  int ptr, rt;

  #define lson t[p].ch[0]
  #define rson t[p].ch[1]
  inline int newnode(int val) {
    ++ptr;
    t[ptr].v = val; t[ptr].w = rand();
    t[ptr].siz = t[ptr].k = 1;
    t[ptr].sum = val;
    return ptr;
  }
  inline void pushup(int p) {
    t[p].siz = t[lson].siz + t[rson].siz + t[p].k;
    t[p].sum = t[lson].sum + t[rson].sum + 1ll * t[p].v * t[p].k;
  }
  inline void rturn(int &p) {
    int q = lson;
    lson = t[q].ch[1]; t[q].ch[1] = p; p = q;
    pushup(rson);
    pushup(p);
  }
  inline void lturn(int &p) {
    int q = rson;
    rson = t[q].ch[0]; t[q].ch[0] = p; p = q;
    pushup(lson);
    pushup(p);
  }
  void Insert(int &p, int x) {
    //printf("%d\n", p);
    if (!p) {
      p = newnode(x);
      return;
    }
    t[p].siz++; t[p].sum += x;
    if (t[p].v == x) {
      t[p].k++;
      //t[p].sum += x;
      return;
    } else if (t[p].v < x) {
      Insert(rson, x);
      if (t[rson].w < t[p].w) lturn(p);
    } else {
      Insert(lson, x);
      if (t[lson].w < t[p].w) rturn(p);
    }
  }
  void Delete(int &p, int x) {
    if (!p) return;
    if (t[p].v == x) {
      if (t[p].k > 1) t[p].k--, t[p].siz--, t[p].sum -= x;
      else {
        if (!(lson && rson)) p = lson + rson;
        else if (t[rson].w > t[lson].w)
          rturn(p), Delete(p, x);
        else lturn(p), Delete(p, x);
      }
    } else {
      t[p].siz--; t[p].sum -= x;
      if (t[p].v < x) Delete(rson, x);
      else Delete(lson, x);
    }
  }
  ll GetLower(int p, int k) {
    //printf("%d %d %d %lld\n", p, t[p].v, k, t[p].sum);
    if (!p) return 0;
    if (t[p].v == k) {
      //printf("ret %lld\n", t[p].sum - t[rson].sum);
      return t[p].sum - t[rson].sum;
    } else if (t[p].v < k) {
      ll ret = t[p].sum - t[rson].sum + GetLower(rson, k);
      //printf("ret %lld\n", ret);
      return ret;
    } else {
      ll ret = GetLower(lson, k);
      //printf("ret %lld\n", ret);
      return ret;
    }
  }
  int GetLowerSize(int p, int k) {
    if (!p) return 0;
    if (t[p].v == k) {
      return t[p].siz - t[rson].siz;
    } else if (t[p].v < k) {
      return t[p].siz - t[rson].siz + GetLowerSize(rson, k);
    } else {
      return GetLowerSize(lson, k);
    }
  }
  #undef lson
  #undef rson  
}A, B;

int main() {
  freopen("graph.in", "r", stdin);
  freopen("graph.out", "w", stdout);
  n = rd();
  for (int i = 1; i <= n; ++i) {
    a[i] = rd(); A.Insert(A.rt, a[i]);
    //printf("%d\n", A.rt);
    //printf("%d\n", A.t[A.rt].siz);
  } 
  for (int i = 1; i <= n; ++i) {
    b[i] = rd(); B.Insert(B.rt, b[i]);
    //printf("%d\n", B.rt);
  }
  for (int i = 1; i <= n; ++i) {
    ll lsum = B.GetLower(B.rt, a[i]);
    int rsiz = n - B.GetLowerSize(B.rt, a[i]);
    //printf("%lld %d\n", lsum, rsiz);
    //puts("---");
    ans += lsum + 1ll * rsiz * a[i];
  }
  printf("%lld\n", ans);
  m = rd();
  int typ, p, x;
  while (m--) {
    typ = rd(); p = rd(); x = rd();
    if (typ) {
      ll lsum = A.GetLower(A.rt, b[p]);
      int rsiz = n - A.GetLowerSize(A.rt, b[p]);
      ans -= lsum + 1ll * rsiz * b[p];
      B.Delete(B.rt, b[p]);
      b[p] = x;
      lsum = A.GetLower(A.rt, b[p]);
      rsiz = n - A.GetLowerSize(A.rt, b[p]);
      ans += lsum + 1ll * rsiz * b[p];
      B.Insert(B.rt, b[p]);
    } else {
      ll lsum = B.GetLower(B.rt, a[p]);
      int rsiz = n - B.GetLowerSize(B.rt, a[p]);
      ans -= lsum + 1ll * rsiz * a[p];
      A.Delete(A.rt, a[p]);
      a[p] = x;
      lsum = B.GetLower(B.rt, a[p]);
      rsiz = n - B.GetLowerSize(B.rt, a[p]);
      ans += lsum + 1ll * rsiz * a[p];
      A.Insert(A.rt, a[p]);
    }
    printf("%lld\n", ans);
  }
  fclose(stdin);
  fclose(stdout);
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/nishikino-curtis/p/10292285.html