Submission #842245

#TimeUsernameProblemLanguageResultExecution timeMemory
842245WLZFancy Fence (CEOI20_fancyfence)C++17
100 / 100
91 ms15312 KiB
#include <bits/stdc++.h>
using namespace std;

#include <iostream>

/**
 * Compute the greatest common divisor d of a and b together 
 * with the x and y such that ax + by = d using the extended Euclidean algorithm
 * 
 * @param integers a, b whose gcd will be computed, references x, y where values will be stored
 * @returns greatest common divisor of a and b
*/
template<typename T1, typename T2>
T1 extgcd(const T1& a, const T1& b, T2 &x, T2 &y) {
    x = 1; y = 0;
    T1 a1(a), b1(b);
    T2 x1 = 0, y1 = 1;
    while (b1 != 0) {
        T1 q = a1 / b1;
        tie(x, x1) = make_pair(x1, x - q * x1);
        tie(y, y1) = make_pair(y1, y - q * y1);
        tie(a1, b1) = make_pair(b1, a1 - q * b1);
    }
    return a1;
}

/**
 * Modular integer implementation
 * NOT completely tested!
*/
template<const int MOD>
class modint {
    private: int x;

    public:
    modint() : x(0) {}

    template<typename T>
    void set(const T _x, bool raw = false) {
        if (raw) x = _x;
        else {
            x = _x % MOD;
            if (x < 0) x += MOD;
        }
    }

    template<typename T>
    modint(const T &_x, bool raw = false) {
        set(_x, raw);
    }

    template<typename T>
    modint<MOD> &operator=(const T &_x) {
        set(_x);
        return *this;
    }

    modint<MOD> &operator+=(const modint<MOD> &rhs) {
        x += rhs.x;
        if (x >= MOD) x -= MOD;
        return *this;
    }
        
    friend modint<MOD> operator+(modint<MOD> lhs, const modint<MOD> &rhs) {
        lhs += rhs;
        return lhs;
    }

    modint<MOD> &operator-=(const modint<MOD> &rhs) {
        x -= rhs.x;
        if (x < 0) x += MOD;
        return *this;
    }
        
    friend modint<MOD> operator-(modint<MOD> lhs, const modint<MOD> &rhs) {
        lhs -= rhs;
        return lhs;
    }

    modint<MOD> &operator*=(const modint<MOD> &rhs) {
        x = (unsigned long long) x * rhs.x % MOD;
        return *this;
    }

    friend modint<MOD> operator*(modint<MOD> lhs, const modint<MOD> &rhs) {
        lhs *= rhs;
        return lhs;
    }

    modint<MOD> inv() const {
        modint x1, y1;
        extgcd(x, MOD, x1, y1);
        return move(x1);
    }

    modint<MOD> &operator/=(const modint<MOD> &rhs) {
        operator*=(rhs.inv());
        return *this;
    }

    friend modint<MOD> operator/(modint<MOD> lhs, const modint<MOD> &rhs) {
        lhs /= rhs;
        return lhs;
    }

    modint<MOD> &operator++() {
        operator+=(1);
        return *this;
    }

    modint<MOD> operator++(int) {
        modint<MOD> old = *this;
        operator++();
        return old;
    }

    modint<MOD> &operator--() {
        operator-=(1);
        return *this;
    }

    modint<MOD> operator--(int) {
        modint<MOD> old = *this;
        operator--();
        return old;
    }

    template<typename T>
    operator T() const {
        return x;
    }

    int val() const {
        return x;
    }
};

template<const int MOD, typename T>
modint<MOD> pow(modint<MOD> a, T b) {
    modint<MOD> ans(1, true);
    while (b != 0) {
        if (b & 1) ans *= a;
        a *= a;
        b >>= 1;
    }
    return ans;
}

template<const int MOD>
std::istream &operator>>(std::istream &is, modint<MOD> &x) {
    unsigned int _x;
    is >> _x;
    x.set(_x, true);
    return is;
}

template<const int MOD>
std::ostream &operator<<(std::ostream &os, const modint<MOD> &x) {
    os << x.val();
    return os;
}

using mint1000000007 = modint<1000000007>;
using mint998244353 = modint<998244353>;

using mint = mint1000000007;

mint f(mint h, mint w) {
    return h * (h + 1) * w * (w + 1) / 4;
}

class dsu {
  private:
    vector<int> p, rank;
    vector<mint> sz;
  public:
    dsu(int n, const vector<mint> &_sz) : sz(_sz) {
      p.assign(n, -1);
      rank.assign(n, 0);
    }

    int root(int x) {
      if (p[x] == -1) {
        return x;
      }
      return (p[x] = root(p[x]));
    }

    bool same_set(int x, int y) {
      return (root(x) == root(y));
    }

    void connect(int x, int y) {
      x = root(x); y = root(y);
      if (x != y) {
        if (rank[x] > rank[y]) {
          p[y] = x;
          sz[x] += sz[y];
        } else {
          p[x] = y;
          sz[y] += sz[x];
          if (rank[x] == rank[y]) {
            rank[y]++;
          }
        }
      }
    }

    mint st_sz(int x) {
      return sz[root(x)];
    }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  vector<mint> h(n), w(n);
  map<int, vector<mint>, greater<int> > mp;
  for (int i = 0; i < n; i++) {
    cin >> h[i];
    mp[h[i]].push_back(i);
  }
  for (int i = 0; i < n; i++) {
    cin >> w[i];
  }
  dsu g(n, w);
  vector<bool> b(n, false);
  mint ans = 0;
  for (auto& p : mp) {
    for (auto& x : p.second) {
      b[x] = true;
      if (x.val() > 0 && b[x - 1] && !g.same_set(x, x - 1)) {
        ans -= f(p.first, g.st_sz(x - 1));
        g.connect(x, x - 1);
      }
      if (x.val() < n - 1 && b[x + 1] && !g.same_set(x, x + 1)) {
        ans -= f(p.first, g.st_sz(x + 1));
        g.connect(x, x + 1);
      }
      ans += f(p.first, g.st_sz(x));
    }
  }
  cout << ans << '\n';
  return 0;
}

Compilation message (stderr)

fancyfence.cpp: In instantiation of 'modint<MOD> modint<MOD>::inv() const [with int MOD = 1000000007]':
fancyfence.cpp:97:24:   required from 'modint<MOD>& modint<MOD>::operator/=(const modint<MOD>&) [with int MOD = 1000000007]'
fancyfence.cpp:102:13:   required from 'modint<1000000007> operator/(modint<1000000007>, const modint<1000000007>&)'
fancyfence.cpp:169:40:   required from here
fancyfence.cpp:93:23: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move]
   93 |         return move(x1);
      |                       ^
fancyfence.cpp:93:23: note: remove 'std::move' call
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...