Submission #787202

#TimeUsernameProblemLanguageResultExecution timeMemory
787202tvladm2009Sightseeing in Kyoto (JOI22_kyoto)C++17
100 / 100
419 ms19700 KiB
#include <bits/stdc++.h>
#define int ll

using namespace std;

typedef long long ll;
typedef long double ld;
const int N = (int) 1e5 + 7;
int a[N];
int b[N];
int h;
int w;

struct Fraction {
  ll a;
  ll b;

  Fraction(ll a, ll b) : a(a), b(b) {

  }
};

ld getld(Fraction fr) {
  return (ld)fr.a / (ld)fr.b;
}

bool operator < (Fraction First, Fraction Second) {
  return (ld)First.a / (ld)First.b <= (ld)Second.a / (ld)Second.b;
}

bool operator == (Fraction First, Fraction Second) {
  return (ld)First.a / (ld)First.b == (ld)Second.a / (ld)Second.b;
}

Fraction operator + (Fraction First, ll Second) {
  return Fraction(First.a + Second * First.b, First.b);
}

Fraction operator + (ll Second, Fraction First) {
  return Fraction(First.a + Second * First.b, First.b);
}

Fraction operator - (Fraction First, ll Second) {
  return Fraction(First.a - Second * First.b, First.b);
}

Fraction operator - (ll Second, Fraction First) {
  return Fraction(-First.a + Second * First.b, First.b);
}

Fraction operator * (Fraction First, ll Second) {
  return {First.a * Second, First.b};
}

Fraction operator * (ll First, Fraction Second) {
  return {Second.a * First, Second.b};
}

struct T {
  Fraction val;
  int ind;
  bool type;
};

bool operator == (T a, T b) {
  return a.val.a == b.val.a && a.val.b == b.val.b && a.ind == b.ind && a.type == b.type;
}

bool operator < (T a, T b) {
  if ((a.val == b.val) == false) {
    return a.val < b.val;
  }
  if (a.ind != b.ind) {
    return a.ind < b.ind;
  }
  return a.type < b.type;
}

struct BIT {
  vector<int> aib;
  int n;

  BIT(int nn) {
    n = nn;
    aib.resize(n + 1);
  }

  void update(int x, int val) {
    for (int i = x; i <= n; i += i & -i) {
      aib[i] += val;
    }
  }

  int query(int x) {
    int ret = 0;
    for (int i = x; i >= 1; i -= i & -i) {
      ret += aib[i];
    }
    return ret;
  }

  int getprev(int x) {
    if (query(x - 1) == 0) {
      return -1;
    }
    int need = query(x - 1);
    int sol = 0;
    int sum = 0;
    for (int b = 20; b >= 0; b--) {
      if (sol + (1 << b) < x && sum + aib[sol + (1 << b)] < need) {
        sum += aib[sol + (1 << b)];
        sol += (1 << b);
      }
    }
    return sol + 1;
  }

  int getnext(int x) {
    if (query(n) - query(x) == 0) {
      return -1;
    }
    int need = query(x) + 1;
    int sol = 0;
    int sum = 0;
    for (int b = 20; b >= 0; b--) {
      if (sol + (1 << b) <= n && sum + aib[sol + (1 << b)] < need) {
        sum += aib[sol + (1 << b)];
        sol += (1 << b);
      }
    }
    return sol + 1;
  }
};

signed main() {
  ios::sync_with_stdio(0); cin.tie(0);

  cin >> h >> w;
  for (int i = 1; i <= h; i++) {
    cin >> a[i];
  }
  for (int i = 1; i <= w; i++) {
    cin >> b[i];
  }
  set<T> s;
  for (int i = 2; i <= h; i++) {
    Fraction fr = {a[i] - a[i - 1], 1};
    s.insert({fr, i, 0});
  }
  for (int i = 2; i <= w; i++) {
    Fraction fr = {b[i] - b[i - 1], 1};
    s.insert({fr, i, 1});
  }
  BIT lines(h), columns(w);
  for (int i = 1; i <= h; i++) {
    lines.update(i, 1);
  }
  for (int i = 1; i <= w; i++) {
    columns.update(i, 1);
  }

  ll ret = 0;
  while (!s.empty()) {
    auto it = s.end();
    it--;
    T aux = *it;
    s.erase(it);
    if (aux.type == 0) {
      int prv = lines.getprev(aux.ind);
      int nxt = lines.getnext(aux.ind);
      Fraction f = aux.val;
      if (prv != -1 && nxt != -1) {
        lines.update(aux.ind, -1);
        Fraction old = {a[nxt] - a[aux.ind], nxt - aux.ind};
        s.erase({old, nxt, 0});
        Fraction fr = {a[nxt] - a[prv], nxt - prv};
        s.insert({fr, nxt, 0});
      } else if (prv != -1 && nxt == -1) {
        lines.update(aux.ind, -1);
        int lastcol = columns.getprev(w + 1);
        ret += (aux.ind - prv) * b[lastcol];
      } else if (prv == -1 && nxt != -1) {
        lines.update(aux.ind, -1);
        int firstcol = columns.getnext(0);
        ret += (nxt - aux.ind) * b[firstcol];
        Fraction old = {a[nxt] - a[aux.ind], nxt - aux.ind};
        s.erase({old, nxt, 0});
      } else {
        break;
      }
    } else {
      int prv = columns.getprev(aux.ind);
      int nxt = columns.getnext(aux.ind);
      Fraction f = aux.val;
      if (prv != -1 && nxt != -1) {
        columns.update(aux.ind, -1);
        Fraction old = {b[nxt] - b[aux.ind], nxt - aux.ind};
        s.erase({old, nxt, 1});
        Fraction fr = {b[nxt] - b[prv], nxt - prv};
        s.insert({fr, nxt, 1});
      } else if (prv != -1 && nxt == -1) {
        columns.update(aux.ind, -1);
        int lastline = lines.getprev(h + 1);
        ret += (aux.ind - prv) * a[lastline];
      } else if (prv == -1 && nxt != -1) {
        columns.update(aux.ind, -1);
        int firstline = lines.getnext(0);
        ret += (nxt - aux.ind) * a[firstline];
        Fraction old = {b[nxt] - b[aux.ind], nxt - aux.ind};
        s.erase({old, nxt, 1});
      } else {
        break;
      }
    }
  }
  cout << ret << "\n";
  return 0;
}

Compilation message (stderr)

kyoto.cpp: In function 'int main()':
kyoto.cpp:171:16: warning: variable 'f' set but not used [-Wunused-but-set-variable]
  171 |       Fraction f = aux.val;
      |                ^
kyoto.cpp:194:16: warning: variable 'f' set but not used [-Wunused-but-set-variable]
  194 |       Fraction f = aux.val;
      |                ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...