<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 6/17/2020, 1:01:35 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "-1" << endl;
  exit(0);
}

// ----- Solve -----

using Bomb = tuple<int, int>;

struct Edge
{
  int src, dst, id, on;
  // ll cost;
  Edge() {}
  Edge(int src, int dst, int id, int on = false) : src{src}, dst{dst}, id{id}, on{on} {}
  // Edge(int src, int dst, ll cost) : src{src}, dst{dst}, cost{cost} {}

  void added_edge(vector<vector<Edge>> &V)
  {
    V[src].push_back(*this);
  }

  void added_rev(vector<vector<Edge>> &V)
  {
    V[dst].push_back(rev());
  }

  Edge rev()
  {
    Edge edge{*this};
    swap(edge.src, edge.dst);
    return edge;
  }
};

class Solve
{
  int N, M;
  vector<Bomb> bombs;
  vector<bool> B;
  vector<vector<Edge>> V;
  vector<bool> table;
  vector<bool> visited;

public:
  Solve(int N, int M) : N{N}, M{M}, bombs(N), B(N + 1), V(N + 1), table(M, false), visited(N + 1, false)
  {
    // bombs
    for (auto i{0}; i < N; ++i)
    {
      int a, b;
      cin >> a >> b;
      bombs[i] = Bomb{a, b};
    }
    sort(bombs.begin(), bombs.end());
#if DEBUG == 1
    for (auto i{0}; i < N; ++i)
    {
      cerr << "bombs[" << i << "] = (" << get<0>(bombs[i]) << ", " << get<1>(bombs[i]) << ")" << endl;
    }
#endif
    // B
    B[0] = get<1>(bombs[0]);
    for (auto i{1}; i < N; ++i)
    {
      B[i] = get<1>(bombs[i]) ^ get<1>(bombs[i - 1]);
    }
    B[N] = get<1>(bombs[N - 1]);
    // V
    for (auto i{0}; i < M; ++i)
    {
      int l, r;
      cin >> l >> r;
      // The following two lines are referring to https://atcoder.jp/contests/abc155/submissions/10163379
      auto v{static_cast<int>(distance(bombs.begin(), lower_bound(bombs.begin(), bombs.end(), Bomb{l, -1})))};
      auto w{static_cast<int>(distance(bombs.begin(), lower_bound(bombs.begin(), bombs.end(), Bomb{r, 2})))};
#if DEBUG == 1
      cerr << "l = " << l << ", r = " << r << ", v = " << v << ", w = " << w << endl;
#endif
      if (v == w)
      {
        continue;
      }
      Edge edge{v, w, i};
      edge.added_edge(V);
      edge.added_rev(V);
    }
  }

  void flush()
  {
    make_table();
    int cnt{0};
    for (auto i{0}; i < M; ++i)
    {
      if (table[i])
      {
        ++cnt;
      }
    }
    cout << cnt << endl;
    for (auto i{0}; i < M; ++i)
    {
      if (table[i])
      {
        cout << i + 1;
      }
      --cnt;
      if (cnt > 0)
      {
        cout << " ";
      }
      else
      {
        cout << endl;
      }
    }
  }

private:
  void make_table()
  {
    for (auto i{0}; i < N + 1; ++i)
    {
      if (!visited[i])
      {
        if (dfs(i) == 1)
        {
          No();
        }
      }
    }
    for (auto i{0}; i < N + 1; ++i)
    {
      for (auto const &e : V[i])
      {
        if (e.on)
        {
          table[e.id] = true;
        }
      }
    }
  }

  int dfs(int src)
  {
    visited[src] = true;
    auto sum{B[src] ? 1 : 0};
    for (auto &e : V[src])
    {
      if (visited[e.dst])
      {
        continue;
      }
      auto tmp{dfs(e.dst)};
      sum += tmp;
      e.on = (tmp == 1);
    }
    return sum & 1;
  }
};

// ----- main() -----

int main()
{
  int N, M;
  cin >> N >> M;
  Solve solve(N, M);
  solve.flush();
}
<commit_msg>tried F.cpp to 'F'<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 6/17/2020, 1:01:35 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "-1" << endl;
  exit(0);
}

// ----- Solve -----

using Bomb = tuple<int, int>;

struct Edge
{
  int src, dst, id, on;
  // ll cost;
  Edge() {}
  Edge(int src, int dst, int id, int on = false) : src{src}, dst{dst}, id{id}, on{on} {}
  // Edge(int src, int dst, ll cost) : src{src}, dst{dst}, cost{cost} {}

  void added_edge(vector<vector<Edge>> &V)
  {
    V[src].push_back(*this);
  }

  void added_rev(vector<vector<Edge>> &V)
  {
    V[dst].push_back(rev());
  }

  Edge rev()
  {
    Edge edge{*this};
    swap(edge.src, edge.dst);
    return edge;
  }
};

class Solve
{
  int N, M;
  vector<Bomb> bombs;
  vector<bool> B;
  vector<vector<Edge>> V;
  vector<bool> table;
  vector<bool> visited;

public:
  Solve(int N, int M) : N{N}, M{M}, bombs(N), B(N + 1), V(N + 1), table(M, false), visited(N + 1, false)
  {
    // bombs
    for (auto i{0}; i < N; ++i)
    {
      int a, b;
      cin >> a >> b;
      bombs[i] = Bomb{a, b};
    }
    sort(bombs.begin(), bombs.end());
#if DEBUG == 1
    for (auto i{0}; i < N; ++i)
    {
      cerr << "bombs[" << i << "] = (" << get<0>(bombs[i]) << ", " << get<1>(bombs[i]) << ")" << endl;
    }
#endif
    // B
    B[0] = get<1>(bombs[0]);
    for (auto i{1}; i < N; ++i)
    {
      B[i] = get<1>(bombs[i]) ^ get<1>(bombs[i - 1]);
    }
    B[N] = get<1>(bombs[N - 1]);
    // V
    for (auto i{0}; i < M; ++i)
    {
      int l, r;
      cin >> l >> r;
      // The following two lines are referring to https://atcoder.jp/contests/abc155/submissions/10163379
      auto v{static_cast<int>(distance(bombs.begin(), lower_bound(bombs.begin(), bombs.end(), Bomb{l, -1})))};
      auto w{static_cast<int>(distance(bombs.begin(), lower_bound(bombs.begin(), bombs.end(), Bomb{r, 2})))};
#if DEBUG == 1
      cerr << "l = " << l << ", r = " << r << ", v = " << v << ", w = " << w << endl;
#endif
      if (v == w)
      {
        continue;
      }
      Edge edge{v, w, i};
      edge.added_edge(V);
      edge.added_rev(V);
    }
  }

  void flush()
  {
    make_table();
    int cnt{0};
    for (auto i{0}; i < M; ++i)
    {
      if (table[i])
      {
        ++cnt;
      }
    }
    cout << cnt << endl;
    for (auto i{0}; i < M; ++i)
    {
      if (table[i])
      {
        cout << i + 1;
        --cnt;
      }
      if (cnt > 0)
      {
        cout << " ";
      }
      else
      {
        cout << endl;
      }
    }
  }

private:
  void make_table()
  {
    for (auto i{0}; i < N + 1; ++i)
    {
      if (!visited[i])
      {
        if (dfs(i) == 1)
        {
          No();
        }
      }
    }
    for (auto i{0}; i < N + 1; ++i)
    {
      for (auto const &e : V[i])
      {
        if (e.on)
        {
          table[e.id] = true;
        }
      }
    }
  }

  int dfs(int src)
  {
    visited[src] = true;
    auto sum{B[src] ? 1 : 0};
    for (auto &e : V[src])
    {
      if (!visited[e.dst])
      {
        continue;
      }
      auto tmp{dfs(e.dst)};
      sum += tmp;
      e.on = (tmp == 1);
    }
    return sum & 1;
  }
};

// ----- main() -----

int main()
{
  int N, M;
  cin >> N >> M;
  Solve solve(N, M);
  solve.flush();
}
<|endoftext|>


<commit_before>
// Copyright (c) 2013,2014, niXman (i dotty nixman doggy gmail dotty com)
// All rights reserved.
//
// This file is part of THROW(https://github.com/niXman/throw) project.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice, this
//   list of conditions and the following disclaimer in the documentation and/or
//   other materials provided with the distribution.
//
//   Neither the name of the {organization} nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef _throw__throw_hpp
#define _throw__throw_hpp

#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>

#include <boost/format.hpp>

#include <stdexcept>
#include <sstream>

/***************************************************************************/
// based on the: http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments

#define __THROW_%PREFIX%_ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define __THROW_%PREFIX%_HAS_COMMA(...) __THROW_%PREFIX%_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define __THROW_%PREFIX%__TRIGGER_PARENTHESIS_(...) ,

#define __THROW_%PREFIX%_ISEMPTY(...) \
	__THROW_%PREFIX%__ISEMPTY( \
		/* test if there is just one argument, eventually an empty one */ \
		__THROW_%PREFIX%_HAS_COMMA(__VA_ARGS__), \
		/* test if _TRIGGER_PARENTHESIS_ together with the argument adds a comma */ \
		__THROW_%PREFIX%_HAS_COMMA(__THROW_%PREFIX%__TRIGGER_PARENTHESIS_ __VA_ARGS__),                 \
		/* test if the argument together with a parenthesis adds a comma */ \
		__THROW_%PREFIX%_HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
		/* test if placing it between _TRIGGER_PARENTHESIS_ and the parenthesis adds a comma */ \
		__THROW_%PREFIX%_HAS_COMMA(__THROW_%PREFIX%__TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
	)

#define __THROW_%PREFIX%_PASTE5(_0, _1, _2, _3, _4) \
	_0 ## _1 ## _2 ## _3 ## _4

#define __THROW_%PREFIX%__ISEMPTY(_0, _1, _2, _3) \
	__THROW_%PREFIX%_HAS_COMMA(__THROW_%PREFIX%_PASTE5(__THROW_%PREFIX%__IS_EMPTY_CASE_, _0, _1, _2, _3))

#define __THROW_%PREFIX%__IS_EMPTY_CASE_0001 \
	,

#define __THROW_%PREFIX%_TUPLE_IS_EMPTY(...) \
	__THROW_%PREFIX%_ISEMPTY(__VA_ARGS__)

/***************************************************************************/

#define __THROW_%PREFIX%_PASTE_ELEM(unused, idx, args) \
	% (BOOST_PP_TUPLE_ELEM(idx, args))

#define __THROW_%PREFIX%_FORMAT_MESSAGE_WITHOUT_ARGS(...)

#define __THROW_%PREFIX%_FORMAT_MESSAGE_WITH_ARGS(...) \
	BOOST_PP_REPEAT( \
		 BOOST_PP_TUPLE_SIZE((__VA_ARGS__)) \
		,__THROW_%PREFIX%_PASTE_ELEM \
		,(__VA_ARGS__) \
	)

/***************************************************************************/

/* usage:
 * std::cout << %PREFIX%_FORMAT_MESSAGE("message: %1%, %2%, %3%", "string1", 33, "string2") << std::endl;
 * std::string str = %PREFIX%_FORMAT_MESSAGE_AS_STRING("message: %1%, %2%, %3%", "string1", 33, "string2");
 */

#define %PREFIX%_FORMAT_MESSAGE(fmt, ...) \
	boost::format( \
		static_cast<const std::ostringstream&>( \
			std::ostringstream() \
				<< __FILE__ "(" BOOST_PP_STRINGIZE(__LINE__) ")[" \
				<< __PRETTY_FUNCTION__ << "]: " \
				<< fmt \
		).str() \
	) \
	BOOST_PP_IF( \
		 __THROW_%PREFIX%_TUPLE_IS_EMPTY(__VA_ARGS__) \
		,__THROW_%PREFIX%_FORMAT_MESSAGE_WITHOUT_ARGS \
		,__THROW_%PREFIX%_FORMAT_MESSAGE_WITH_ARGS \
	)(__VA_ARGS__)

#define %PREFIX%_FORMAT_MESSAGE_AS_STRING(fmt, ...) \
	(%PREFIX%_FORMAT_MESSAGE(fmt, __VA_ARGS__)).str()

/***************************************************************************/

/* usage:
 * %PREFIX%_THROW("message: %1%, %2%, %3%", "string1", 33, "string2");
 */

#define %PREFIX%_THROW(fmt, ...) \
	throw std::runtime_error(%PREFIX%_FORMAT_MESSAGE_AS_STRING(fmt, __VA_ARGS__))

/***************************************************************************/

/* usage:
 * %PREFIX%_TYPED_THROW(std::logic_error, "message: %1%, %2%, %3%", "string1", 33, "string2");
 */

#define %PREFIX%_TYPED_THROW(extype, fmt, ...) \
	throw extype(%PREFIX%_FORMAT_MESSAGE_AS_STRING(fmt, __VA_ARGS__))

/***************************************************************************/

/* usage:
 * %PREFIX%_TRY(exception_is_thrown) {
 *    ...code...
 * } %PREFIX%_CATCH(exception_is_thrown)
 * if ( exception_is_thrown ) {
 *    ...processing...
 * }
 *
 * usage:
 * %PREFIX%_TRY(exception_is_thrown) {
 *    ...code...
 * } %PREFIX%_CATCH_LOG(exception_is_thrown, std::cerr)
 * if ( exception_is_thrown ) {
 *    ...processing...
 * }
 */

#define %PREFIX%_TRY(flagname) \
	bool flagname = false; \
	((void)flagname); \
	try

#define %PREFIX%_CATCH(flagname, ...) \
	catch (const std::exception &) { \
		flagname = true; \
		{ __VA_ARGS__; } \
	} catch (...) { \
		flagname = true; \
		{ __VA_ARGS__; } \
	}

#define %PREFIX%_CATCH_LOG(flagname, logstream, ...) \
	catch (const std::exception &ex) { \
		flagname = true; \
		logstream << %PREFIX%_FORMAT_MESSAGE("[exception]: %1%", ex.what()) << std::endl; \
		{ __VA_ARGS__; } \
	} catch (...) { \
		flagname = true; \
		logstream << %PREFIX%_FORMAT_MESSAGE("[exception]: unknown exception") << std::endl; \
		{ __VA_ARGS__; } \
	}

/***************************************************************************/

#define %PREFIX%_TEST_THROW(expr) \
	do { \
		if ( !(expr) ) { \
			throw std::runtime_error( \
				%PREFIX%_FORMAT_MESSAGE_AS_STRING("[test failed]: expression: \" #expr \"") \
			); \
		} \
	} while(0)

/***************************************************************************/

#endif // _throw__throw_hpp
<commit_msg>Update throw.hpp<commit_after>
// Copyright (c) 2013,2014, niXman (i dotty nixman doggy gmail dotty com)
// All rights reserved.
//
// This file is part of THROW(https://github.com/niXman/throw) project.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice, this
//   list of conditions and the following disclaimer in the documentation and/or
//   other materials provided with the distribution.
//
//   Neither the name of the {organization} nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef _throw__throw_hpp
#define _throw__throw_hpp

#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>

#include <boost/format.hpp>

#include <stdexcept>
#include <sstream>

/***************************************************************************/
// based on the: http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments

#define __THROW_%PREFIX%_ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define __THROW_%PREFIX%_HAS_COMMA(...) __THROW_%PREFIX%_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define __THROW_%PREFIX%__TRIGGER_PARENTHESIS_(...) ,

#define __THROW_%PREFIX%_ISEMPTY(...) \
	__THROW_%PREFIX%__ISEMPTY( \
		/* test if there is just one argument, eventually an empty one */ \
		__THROW_%PREFIX%_HAS_COMMA(__VA_ARGS__), \
		/* test if _TRIGGER_PARENTHESIS_ together with the argument adds a comma */ \
		__THROW_%PREFIX%_HAS_COMMA(__THROW_%PREFIX%__TRIGGER_PARENTHESIS_ __VA_ARGS__),                 \
		/* test if the argument together with a parenthesis adds a comma */ \
		__THROW_%PREFIX%_HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
		/* test if placing it between _TRIGGER_PARENTHESIS_ and the parenthesis adds a comma */ \
		__THROW_%PREFIX%_HAS_COMMA(__THROW_%PREFIX%__TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
	)

#define __THROW_%PREFIX%_PASTE5(_0, _1, _2, _3, _4) \
	_0 ## _1 ## _2 ## _3 ## _4

#define __THROW_%PREFIX%__ISEMPTY(_0, _1, _2, _3) \
	__THROW_%PREFIX%_HAS_COMMA(__THROW_%PREFIX%_PASTE5(__THROW_%PREFIX%__IS_EMPTY_CASE_, _0, _1, _2, _3))

#define __THROW_%PREFIX%__IS_EMPTY_CASE_0001 \
	,

#define __THROW_%PREFIX%_TUPLE_IS_EMPTY(...) \
	__THROW_%PREFIX%_ISEMPTY(__VA_ARGS__)

/***************************************************************************/

#define __THROW_%PREFIX%_PASTE_ELEM(unused, idx, args) \
	% (BOOST_PP_TUPLE_ELEM(idx, args))

#define __THROW_%PREFIX%_FORMAT_MESSAGE_WITHOUT_ARGS(...)

#define __THROW_%PREFIX%_FORMAT_MESSAGE_WITH_ARGS(...) \
	BOOST_PP_REPEAT( \
		 BOOST_PP_TUPLE_SIZE((__VA_ARGS__)) \
		,__THROW_%PREFIX%_PASTE_ELEM \
		,(__VA_ARGS__) \
	)

/***************************************************************************/

/* usage:
 * std::cout << %PREFIX%_FORMAT_MESSAGE("message: %1%, %2%, %3%", "string1", 33, "string2") << std::endl;
 * std::string str = %PREFIX%_FORMAT_MESSAGE_AS_STRING("message: %1%, %2%, %3%", "string1", 33, "string2");
 */

#define %PREFIX%_FORMAT_MESSAGE(fmt, ...) \
	boost::format( \
		static_cast<const std::ostringstream&>( \
			std::ostringstream() \
				<< __FILE__ "(" BOOST_PP_STRINGIZE(__LINE__) ")[" \
				<< __PRETTY_FUNCTION__ << "]: " \
				<< fmt \
		).str() \
	) \
	BOOST_PP_IF( \
		 __THROW_%PREFIX%_TUPLE_IS_EMPTY(__VA_ARGS__) \
		,__THROW_%PREFIX%_FORMAT_MESSAGE_WITHOUT_ARGS \
		,__THROW_%PREFIX%_FORMAT_MESSAGE_WITH_ARGS \
	)(__VA_ARGS__)

#define %PREFIX%_FORMAT_MESSAGE_AS_STRING(fmt, ...) \
	(%PREFIX%_FORMAT_MESSAGE(fmt, __VA_ARGS__)).str()

/***************************************************************************/

/* usage:
 * %PREFIX%_THROW("message: %1%, %2%, %3%", "string1", 33, "string2");
 */

#define %PREFIX%_THROW(fmt, ...) \
	throw std::runtime_error(%PREFIX%_FORMAT_MESSAGE_AS_STRING(fmt, __VA_ARGS__))

/***************************************************************************/

/* usage:
 * %PREFIX%_TYPED_THROW(std::logic_error, "message: %1%, %2%, %3%", "string1", 33, "string2");
 */

#define %PREFIX%_TYPED_THROW(extype, fmt, ...) \
	throw extype(%PREFIX%_FORMAT_MESSAGE_AS_STRING(fmt, __VA_ARGS__))

/***************************************************************************/

/* usage:
 * %PREFIX%_TRY(exception_is_thrown) {
 *    ...code...
 * } %PREFIX%_CATCH(exception_is_thrown)
 * if ( exception_is_thrown ) {
 *    ...processing...
 * }
 *
 * usage:
 * %PREFIX%_TRY(exception_is_thrown) {
 *    ...code...
 * } %PREFIX%_CATCH_LOG(exception_is_thrown, std::cerr)
 * if ( exception_is_thrown ) {
 *    ...processing...
 * }
 */

#define %PREFIX%_TRY(flagname) \
	bool flagname = false; \
	((void)flagname); \
	try

#define %PREFIX%_CATCH(flagname, ...) \
	catch (const std::exception &) { \
		flagname = true; \
		{ __VA_ARGS__; } \
	} catch (...) { \
		flagname = true; \
		{ __VA_ARGS__; } \
	}

#define %PREFIX%_CATCH_LOG(flagname, logstream, ...) \
	catch (const std::exception &ex) { \
		flagname = true; \
		logstream << %PREFIX%_FORMAT_MESSAGE("[exception]: %1%", ex.what()) << std::endl; \
		{ __VA_ARGS__; } \
	} catch (...) { \
		flagname = true; \
		logstream << %PREFIX%_FORMAT_MESSAGE("[exception]: unknown exception") << std::endl; \
		{ __VA_ARGS__; } \
	}

/***************************************************************************/

#define %PREFIX%_TEST_TYPED_THROW(expr, type) \
	do { \
		if ( !(expr) ) { \
			throw type( \
				%PREFIX%_FORMAT_MESSAGE_AS_STRING("[test failed]: expression: \"" #expr "\"") \
			); \
		} \
	} while(0)

#define %PREFIX%_TEST_THROW(expr) \
	%PREFIX%_TEST_TYPED_THROW(expr, std::runtime_error)

/***************************************************************************/

#endif // _throw__throw_hpp
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/23 5:42:51
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- ReadGraph -----
// Referring to ymatsux-san's source code: https://atcoder.jp/contests/abc138/submissions/7016619

struct Edge
{
  int src, dst, id, rev;
  // ll cost;
  Edge() {}
  Edge(int src, int dst, int id, int rev) : src{src}, dst{dst}, id{id}, rev{rev} {}

  void added_edge(vector<vector<Edge>> &V)
  {
    V[src].push_back(*this);
  }

  void added_rev(vector<vector<Edge>> &V)
  {
    V[dst].push_back(rev_edge());
  }

  Edge rev_edge()
  {
    Edge edge{*this};
    swap(edge.src, edge.dst);
    swap(edge.id, edge.rev);
    return edge;
  }
};

enum class GraphType
{
  Undirected,
  Directed,
  RevEdge,
};

tuple<vector<vector<Edge>>, vector<Edge>> ReadGraphWithEdges(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  vector<vector<Edge>> V(N);
  vector<Edge> E;
  for (auto i = 0; i < M; ++i)
  {
    int v, w;
    cin >> v >> w;
    if (is_one_indexed)
    {
      --v;
      --w;
    }
    switch (type)
    {
    case GraphType::Undirected:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      break;
    }
    case GraphType::Directed:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      E.push_back(edge);
      break;
    }
    case GraphType::RevEdge:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size()) + 1};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      E.push_back(edge.rev_edge());
      break;
    }
    default:
      break;
    }
  }
  return make_tuple(V, E);
}

vector<vector<Edge>> ReadGraph(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return get<0>(ReadGraphWithEdges(N, M, type, is_one_indexed));
}

tuple<vector<vector<Edge>>, vector<Edge>> ReadTreeWithEdges(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraphWithEdges(N, N - 1, type, is_one_indexed);
}

vector<vector<Edge>> ReadTree(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraph(N, N - 1, type, is_one_indexed);
}

// ----- Solve -----

struct SubTree
{
  int id, size;
};

class Solve
{
  int N, id;
  vector<queue<SubTree>> Q;
  vector<int> C;
  vector<vector<Edge>> V;
  vector<vector<ll>> S;
  vector<int> color_to_count;

public:
  Solve(int N) : N{N}, id{0}, Q(N), C(N), S(N), color_to_count(N, 0)
  {
    for (auto i{0}; i < N; ++i)
    {
      cin >> C[i];
      C[i]--;
      color_to_count[C[i]]++;
    }
    V = ReadTree(N);
  }

  void flush()
  {
    dfs();
    for (auto i{0}; i < N; ++i)
    {
      auto sum{accumulate(S[i].begin(), S[i].end(), 0)};
      S[i].push_back(N - sum - color_to_count[i]);
      ll ans{0};
      for (auto e : S[i])
      {
        ans += e * (e + 1) / 2;
      }
      cout << N * (N + 1) / 2 - ans << endl;
    }
  }

private:
  int dfs(int src = 0, int parent = -1)
  {
    auto src_id{id++};
    auto &subtree_queue{Q[C[src]]};
    for (auto const &e : V[src])
    {
      if (e.dst == parent)
      {
        continue;
      }
      auto colorless_tree_size{dfs(e.dst, src)};
      while (!Q.empty() && subtree_queue.front().id > src_id)
      {
        colorless_tree_size -= subtree_queue.front().size;
        subtree_queue.pop();
      }
      S[C[src]].push_back(colorless_tree_size);
    }
    auto subtree_size{id - src_id + 1};
    subtree_queue.push(SubTree{src_id, subtree_size});
    return subtree_size;
  }
};

// ----- main() -----

int main()
{
  int N;
  cin >> N;
  Solve solve(N);
  solve.flush();
}
<commit_msg>tried F.cpp to 'F'<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/23 5:42:51
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- ReadGraph -----
// Referring to ymatsux-san's source code: https://atcoder.jp/contests/abc138/submissions/7016619

struct Edge
{
  int src, dst, id, rev;
  // ll cost;
  Edge() {}
  Edge(int src, int dst, int id, int rev) : src{src}, dst{dst}, id{id}, rev{rev} {}

  void added_edge(vector<vector<Edge>> &V)
  {
    V[src].push_back(*this);
  }

  void added_rev(vector<vector<Edge>> &V)
  {
    V[dst].push_back(rev_edge());
  }

  Edge rev_edge()
  {
    Edge edge{*this};
    swap(edge.src, edge.dst);
    swap(edge.id, edge.rev);
    return edge;
  }
};

enum class GraphType
{
  Undirected,
  Directed,
  RevEdge,
};

tuple<vector<vector<Edge>>, vector<Edge>> ReadGraphWithEdges(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  vector<vector<Edge>> V(N);
  vector<Edge> E;
  for (auto i = 0; i < M; ++i)
  {
    int v, w;
    cin >> v >> w;
    if (is_one_indexed)
    {
      --v;
      --w;
    }
    switch (type)
    {
    case GraphType::Undirected:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      break;
    }
    case GraphType::Directed:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      E.push_back(edge);
      break;
    }
    case GraphType::RevEdge:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size()) + 1};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      E.push_back(edge.rev_edge());
      break;
    }
    default:
      break;
    }
  }
  return make_tuple(V, E);
}

vector<vector<Edge>> ReadGraph(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return get<0>(ReadGraphWithEdges(N, M, type, is_one_indexed));
}

tuple<vector<vector<Edge>>, vector<Edge>> ReadTreeWithEdges(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraphWithEdges(N, N - 1, type, is_one_indexed);
}

vector<vector<Edge>> ReadTree(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraph(N, N - 1, type, is_one_indexed);
}

// ----- Solve -----

struct SubTree
{
  int id, size;
};

class Solve
{
  int N, id;
  vector<queue<SubTree>> Q;
  vector<int> C;
  vector<vector<Edge>> V;
  vector<vector<ll>> S;
  vector<int> color_to_count;

public:
  Solve(int N) : N{N}, id{0}, Q(N), C(N), S(N), color_to_count(N, 0)
  {
    for (auto i{0}; i < N; ++i)
    {
      cin >> C[i];
      C[i]--;
      color_to_count[C[i]]++;
    }
    V = ReadTree(N);
  }

  void flush()
  {
    dfs();
    for (auto i{0}; i < N; ++i)
    {
      auto sum{accumulate(S[i].begin(), S[i].end(), 0)};
      S[i].push_back(N - sum - color_to_count[i]);
      ll ans{0};
      for (auto e : S[i])
      {
        ans += e * (e + 1) / 2;
      }
#if DEBUG == 1
      cerr << "S[" << i << "] : ";
      for (auto e : S[i])
      {
        cerr << e << ", ";
      }
      cerr << endl;
#endif
      cout << N * (N + 1) / 2 - ans << endl;
    }
  }

private:
  int dfs(int src = 0, int parent = -1)
  {
    auto src_id{id++};
    auto &subtree_queue{Q[C[src]]};
    for (auto const &e : V[src])
    {
      if (e.dst == parent)
      {
        continue;
      }
      auto colorless_tree_size{dfs(e.dst, src)};
      while (!Q.empty() && subtree_queue.front().id > src_id)
      {
        colorless_tree_size -= subtree_queue.front().size;
        subtree_queue.pop();
      }
      S[C[src]].push_back(colorless_tree_size);
    }
    auto subtree_size{id - src_id + 1};
    subtree_queue.push(SubTree{src_id, subtree_size});
    return subtree_size;
  }
};

// ----- main() -----

int main()
{
  int N;
  cin >> N;
  Solve solve(N);
  solve.flush();
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 7/6/2020, 2:15:24 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

combination C;

mint f(ll x, ll y)
{
  return C(x + y, x);
}

int main()
{
  ll h, w, a, b;
  cin >> h >> w >> a >> b;
  mint ans{0};
  for (auto j{w}; j < b; ++j)
  {
    ans += f(h - a - 1, j) * (h - 1 - (h - a), w - 1 - j);
  }
  cout << ans << endl;
}
<commit_msg>tried D.cpp to 'D'<commit_after>#define DEBUG 1
/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 7/6/2020, 2:15:24 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

combination C;

mint f(ll x, ll y)
{
  return C(x + y, x);
}

int main()
{
  ll h, w, a, b;
  cin >> h >> w >> a >> b;
  mint ans{0};
  for (auto j{w}; j < b; ++j)
  {
    ans += f(h - a - 1, j) * f(h - 1 - (h - a), w - 1 - j);
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>#pragma once

namespace odlib
{
    /// <summary>
    /// A class that can act as an event.
    /// </summary>
    /// <typeparam name="T">The type of the function for the event.</typeparam>
    template<typename T>
    class event
    {
    public:

        event() = default;
        ~event() = default;

        /// <summary>
        /// Notify the subscribers.
        /// </summary>
        /// <typeparam name="Args">The arguments for the function of the event.</typeparam>
        template<typename... Args>
        void notify(Args&& ...args)
        {
            for (auto& subscriber : m_subscribers)
            {
                subscriber.second(std::forward<Args>(args)...);
            }
        }

        /// <summary>
        /// Subscribe a function to the event.
        /// </summary>
        /// <param name="key">Key of the subscriber.</param>
        /// <param name="function">Function to call when the subscribers are notify.</param>
        void subscribe(const std::wstring& key, const std::function<T> function)
        {
            auto subscriber = m_subscribers.find(key);

            if (subscriber == m_subscribers.end())
            {
                m_subscribers.emplace(key, function);

#ifdef _DEBUG
                LOG_DEBUG << L"A subscriber with key " << std::quoted(key) << L" was added";
#endif
            }
            else
            {
                LOG_WARNING << L"A subscriber with key " << std::quoted(key) << L" already exists";
            }
        }

        /// <summary>
        /// Unsubscribe a function to the event.
        /// </summary>
        /// <param name="key">Key of the subscriber.</param>
        void unsubscribe(const std::wstring& key)
        {
            auto subscriber = m_subscribers.find(key);

            if (subscriber != m_subscribers.end())
            {
                m_subscribers.erase(subscriber);

#ifdef _DEBUG
                LOG_DEBUG << L"A subscriber with key " << std::quoted(key) << L" was removed";
#endif
            }
            else
            {
                LOG_WARNING << L"A subscriber with key " << std::quoted(key) << L" doesn't exists";
            }
        }

    private:

        std::map<std::wstring, std::function<T>> m_subscribers;
    };
}<commit_msg>Don't show log messages for event class if it isn't in debug configuration<commit_after>#pragma once

namespace odlib
{
    /// <summary>
    /// A class that can act as an event.
    /// </summary>
    /// <typeparam name="T">The type of the function for the event.</typeparam>
    template<typename T>
    class event
    {
    public:

        event() = default;
        ~event() = default;

        /// <summary>
        /// Notify the subscribers.
        /// </summary>
        /// <typeparam name="Args">The arguments for the function of the event.</typeparam>
        template<typename... Args>
        void notify(Args&& ...args)
        {
            for (auto& subscriber : m_subscribers)
            {
                subscriber.second(std::forward<Args>(args)...);
            }
        }

        /// <summary>
        /// Subscribe a function to the event.
        /// </summary>
        /// <param name="key">Key of the subscriber.</param>
        /// <param name="function">Function to call when the subscribers are notify.</param>
        void subscribe(const std::wstring& key, const std::function<T> function)
        {
            auto subscriber = m_subscribers.find(key);

            if (subscriber == m_subscribers.end())
            {
                m_subscribers.emplace(key, function);

#ifdef _DEBUG
                LOG_DEBUG << L"A subscriber with key " << std::quoted(key) << L" was added";
#endif
            }
#ifdef _DEBUG
            else
            {
                LOG_WARNING << L"A subscriber with key " << std::quoted(key) << L" already exists";
            }
#endif
        }

        /// <summary>
        /// Unsubscribe a function to the event.
        /// </summary>
        /// <param name="key">Key of the subscriber.</param>
        void unsubscribe(const std::wstring& key)
        {
            auto subscriber = m_subscribers.find(key);

            if (subscriber != m_subscribers.end())
            {
                m_subscribers.erase(subscriber);

#ifdef _DEBUG
                LOG_DEBUG << L"A subscriber with key " << std::quoted(key) << L" was removed";
#endif
            }
#ifdef _DEBUG
            else
            {
                LOG_WARNING << L"A subscriber with key " << std::quoted(key) << L" doesn't exists";
            }
#endif
        }

    private:

        std::map<std::wstring, std::function<T>> m_subscribers;
    };
}<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/loadtimes_extension_bindings.h"

#include <math.h>

#include "base/time.h"
#include "chrome/renderer/navigation_state.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "v8/include/v8.h"

using WebKit::WebDataSource;
using WebKit::WebFrame;
using WebKit::WebNavigationType;

// Values for CSI "tran" property
const int kTransitionLink = 0;
const int kTransitionForwardBack = 6;
const int kTransitionOther = 15;
const int kTransitionReload = 16;

namespace extensions_v8 {

static const char* const kLoadTimesExtensionName = "v8/LoadTimes";

class LoadTimesExtensionWrapper : public v8::Extension {
 public:
  // Creates an extension which adds a new function, chromium.GetLoadTimes()
  // This function returns an object containing the following members:
  // requestTime: The time the request to load the page was received
  // loadTime: The time the renderer started the load process
  // finishDocumentLoadTime: The time the document itself was loaded
  //                         (this is before the onload() method is fired)
  // finishLoadTime: The time all loading is done, after the onload()
  //                 method and all resources
  // navigationType: A string describing what user action initiated the load
  LoadTimesExtensionWrapper() :
    v8::Extension(kLoadTimesExtensionName,
      "var chrome;"
      "if (!chrome)"
      "  chrome = {};"
      "chrome.loadTimes = function() {"
      "  native function GetLoadTimes();"
      "  return GetLoadTimes();"
      "};"
      "chrome.csi = function() {"
      "  native function GetCSI();"
      "  return GetCSI();"
      "}") {}

  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
      v8::Handle<v8::String> name) {
    if (name->Equals(v8::String::New("GetLoadTimes"))) {
      return v8::FunctionTemplate::New(GetLoadTimes);
    } else if (name->Equals(v8::String::New("GetCSI"))) {
      return v8::FunctionTemplate::New(GetCSI);
    }
    return v8::Handle<v8::FunctionTemplate>();
  }

  static const char* GetNavigationType(WebNavigationType nav_type) {
    switch (nav_type) {
      case WebKit::WebNavigationTypeLinkClicked:
        return "LinkClicked";
      case WebKit::WebNavigationTypeFormSubmitted:
        return "FormSubmitted";
      case WebKit::WebNavigationTypeBackForward:
        return "BackForward";
      case WebKit::WebNavigationTypeReload:
        return "Reload";
      case WebKit::WebNavigationTypeFormResubmitted:
        return "Resubmitted";
      case WebKit::WebNavigationTypeOther:
        return "Other";
    }
    return "";
  }

  static int GetCSITransitionType(WebNavigationType nav_type) {
    switch (nav_type) {
      case WebKit::WebNavigationTypeLinkClicked:
      case WebKit::WebNavigationTypeFormSubmitted:
      case WebKit::WebNavigationTypeFormResubmitted:
        return kTransitionLink;
      case WebKit::WebNavigationTypeBackForward:
        return kTransitionForwardBack;
      case WebKit::WebNavigationTypeReload:
        return kTransitionReload;
      case WebKit::WebNavigationTypeOther:
        return kTransitionOther;
    }
    return kTransitionOther;
  }

  static v8::Handle<v8::Value> GetLoadTimes(const v8::Arguments& args) {
    WebFrame* frame = WebFrame::frameForEnteredContext();
    if (frame) {
      WebDataSource* data_source = frame->dataSource();
      if (data_source) {
        NavigationState* navigation_state =
            NavigationState::FromDataSource(data_source);
        v8::Local<v8::Object> load_times = v8::Object::New();
        load_times->Set(
            v8::String::New("requestTime"),
            v8::Number::New(navigation_state->request_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("startLoadTime"),
            v8::Number::New(navigation_state->start_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("commitLoadTime"),
            v8::Number::New(navigation_state->commit_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("finishDocumentLoadTime"),
            v8::Number::New(
                navigation_state->finish_document_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("finishLoadTime"),
            v8::Number::New(navigation_state->finish_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("firstPaintTime"),
            v8::Number::New(navigation_state->first_paint_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("firstPaintAfterLoadTime"),
            v8::Number::New(
                navigation_state->first_paint_after_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("navigationType"),
            v8::String::New(GetNavigationType(data_source->navigationType())));
        load_times->Set(
            v8::String::New("wasFetchedViaSpdy"),
            v8::Boolean::New(navigation_state->was_fetched_via_spdy()));
        return load_times;
      }
    }
    return v8::Null();
  }

  static v8::Handle<v8::Value> GetCSI(const v8::Arguments& args) {
    WebFrame* frame = WebFrame::frameForEnteredContext();
    if (frame) {
      WebDataSource* data_source = frame->dataSource();
      if (data_source) {
        NavigationState* navigation_state =
            NavigationState::FromDataSource(data_source);
        v8::Local<v8::Object> csi = v8::Object::New();
        base::Time now = base::Time::Now();
        base::Time start = navigation_state->request_time().is_null() ?
            navigation_state->start_load_time() :
            navigation_state->request_time();
        base::Time onload = navigation_state->finish_document_load_time();
        base::TimeDelta page = now - start;
        csi->Set(
            v8::String::New("startE"),
            v8::Number::New(floor(start.ToDoubleT() * 1000)));
        csi->Set(
            v8::String::New("onloadT"),
            v8::Number::New(floor(onload.ToDoubleT() * 1000)));
        csi->Set(
          v8::String::New("pageT"),
          v8::Number::New(page.InMillisecondsF()));
        csi->Set(
            v8::String::New("tran"),
            v8::Number::New(
                GetCSITransitionType(data_source->navigationType())));

        return csi;
      }
    }
    return v8::Null();
  }
};

v8::Extension* LoadTimesExtension::Get() {
  return new LoadTimesExtensionWrapper();
}

}  // namespace extensions_v8
<commit_msg>Change the javascript context used by the loadtimes extension.  It should be using the CurrentContext, not the EnteredContext so that it grabs the right object based on the frame being called.<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/loadtimes_extension_bindings.h"

#include <math.h>

#include "base/time.h"
#include "chrome/renderer/navigation_state.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "v8/include/v8.h"

using WebKit::WebDataSource;
using WebKit::WebFrame;
using WebKit::WebNavigationType;

// Values for CSI "tran" property
const int kTransitionLink = 0;
const int kTransitionForwardBack = 6;
const int kTransitionOther = 15;
const int kTransitionReload = 16;

namespace extensions_v8 {

static const char* const kLoadTimesExtensionName = "v8/LoadTimes";

class LoadTimesExtensionWrapper : public v8::Extension {
 public:
  // Creates an extension which adds a new function, chromium.GetLoadTimes()
  // This function returns an object containing the following members:
  // requestTime: The time the request to load the page was received
  // loadTime: The time the renderer started the load process
  // finishDocumentLoadTime: The time the document itself was loaded
  //                         (this is before the onload() method is fired)
  // finishLoadTime: The time all loading is done, after the onload()
  //                 method and all resources
  // navigationType: A string describing what user action initiated the load
  LoadTimesExtensionWrapper() :
    v8::Extension(kLoadTimesExtensionName,
      "var chrome;"
      "if (!chrome)"
      "  chrome = {};"
      "chrome.loadTimes = function() {"
      "  native function GetLoadTimes();"
      "  return GetLoadTimes();"
      "};"
      "chrome.csi = function() {"
      "  native function GetCSI();"
      "  return GetCSI();"
      "}") {}

  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
      v8::Handle<v8::String> name) {
    if (name->Equals(v8::String::New("GetLoadTimes"))) {
      return v8::FunctionTemplate::New(GetLoadTimes);
    } else if (name->Equals(v8::String::New("GetCSI"))) {
      return v8::FunctionTemplate::New(GetCSI);
    }
    return v8::Handle<v8::FunctionTemplate>();
  }

  static const char* GetNavigationType(WebNavigationType nav_type) {
    switch (nav_type) {
      case WebKit::WebNavigationTypeLinkClicked:
        return "LinkClicked";
      case WebKit::WebNavigationTypeFormSubmitted:
        return "FormSubmitted";
      case WebKit::WebNavigationTypeBackForward:
        return "BackForward";
      case WebKit::WebNavigationTypeReload:
        return "Reload";
      case WebKit::WebNavigationTypeFormResubmitted:
        return "Resubmitted";
      case WebKit::WebNavigationTypeOther:
        return "Other";
    }
    return "";
  }

  static int GetCSITransitionType(WebNavigationType nav_type) {
    switch (nav_type) {
      case WebKit::WebNavigationTypeLinkClicked:
      case WebKit::WebNavigationTypeFormSubmitted:
      case WebKit::WebNavigationTypeFormResubmitted:
        return kTransitionLink;
      case WebKit::WebNavigationTypeBackForward:
        return kTransitionForwardBack;
      case WebKit::WebNavigationTypeReload:
        return kTransitionReload;
      case WebKit::WebNavigationTypeOther:
        return kTransitionOther;
    }
    return kTransitionOther;
  }

  static v8::Handle<v8::Value> GetLoadTimes(const v8::Arguments& args) {
    WebFrame* frame = WebFrame::frameForCurrentContext();
    if (frame) {
      WebDataSource* data_source = frame->dataSource();
      if (data_source) {
        NavigationState* navigation_state =
            NavigationState::FromDataSource(data_source);
        v8::Local<v8::Object> load_times = v8::Object::New();
        load_times->Set(
            v8::String::New("requestTime"),
            v8::Number::New(navigation_state->request_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("startLoadTime"),
            v8::Number::New(navigation_state->start_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("commitLoadTime"),
            v8::Number::New(navigation_state->commit_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("finishDocumentLoadTime"),
            v8::Number::New(
                navigation_state->finish_document_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("finishLoadTime"),
            v8::Number::New(navigation_state->finish_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("firstPaintTime"),
            v8::Number::New(navigation_state->first_paint_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("firstPaintAfterLoadTime"),
            v8::Number::New(
                navigation_state->first_paint_after_load_time().ToDoubleT()));
        load_times->Set(
            v8::String::New("navigationType"),
            v8::String::New(GetNavigationType(data_source->navigationType())));
        load_times->Set(
            v8::String::New("wasFetchedViaSpdy"),
            v8::Boolean::New(navigation_state->was_fetched_via_spdy()));
        return load_times;
      }
    }
    return v8::Null();
  }

  static v8::Handle<v8::Value> GetCSI(const v8::Arguments& args) {
    WebFrame* frame = WebFrame::frameForCurrentContext();
    if (frame) {
      WebDataSource* data_source = frame->dataSource();
      if (data_source) {
        NavigationState* navigation_state =
            NavigationState::FromDataSource(data_source);
        v8::Local<v8::Object> csi = v8::Object::New();
        base::Time now = base::Time::Now();
        base::Time start = navigation_state->request_time().is_null() ?
            navigation_state->start_load_time() :
            navigation_state->request_time();
        base::Time onload = navigation_state->finish_document_load_time();
        base::TimeDelta page = now - start;
        csi->Set(
            v8::String::New("startE"),
            v8::Number::New(floor(start.ToDoubleT() * 1000)));
        csi->Set(
            v8::String::New("onloadT"),
            v8::Number::New(floor(onload.ToDoubleT() * 1000)));
        csi->Set(
          v8::String::New("pageT"),
          v8::Number::New(page.InMillisecondsF()));
        csi->Set(
            v8::String::New("tran"),
            v8::Number::New(
                GetCSITransitionType(data_source->navigationType())));

        return csi;
      }
    }
    return v8::Null();
  }
};

v8::Extension* LoadTimesExtension::Get() {
  return new LoadTimesExtensionWrapper();
}

}  // namespace extensions_v8
<|endoftext|>


<commit_before>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      config.hh
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   Translator configuration
 *
 * $Id:$
 *
 ********************************************************************/
#ifndef __CONFIG_HH__
#define __CONFIG_HH__

#include <stdint.h>

class Config
{
public:
  Config()
  {
    this->traceRange[0] = 0;
    this->traceRange[1] = 0;

    this->traceStores = false;
  }

  uint32_t traceRange[2]; /* start, end */

  bool traceStores;
};

extern Config *config;

#endif /* !__CONFIG_HH__ */
<commit_msg>Added option to *enable* call table optimization<commit_after>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      config.hh
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   Translator configuration
 *
 * $Id:$
 *
 ********************************************************************/
#ifndef __CONFIG_HH__
#define __CONFIG_HH__

#include <stdint.h>

class Config
{
public:
  Config()
  {
    this->traceRange[0] = 0;
    this->traceRange[1] = 0;

    this->traceStores = false;
    this->optimizeCallTable = false;
  }

  uint32_t traceRange[2]; /* start, end */
  bool traceStores;
  bool optimizeCallTable;
};

extern Config *config;

#endif /* !__CONFIG_HH__ */
<|endoftext|>


<commit_before>//==============================================================================
// Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved.
/// \author AMD Developer Tools Team
/// \file
/// \brief  Vulkan utility functions implementation
//==============================================================================

#include <assert.h>

#include "VkUtils.h"
#include "VkEntrypoints.h"
#include "Logging.h"

bool VkUtils::GetPhysicalDeviceGpaFeaturesAMD(VkPhysicalDevice vkPhysicalDevice, VkPhysicalDeviceGpaFeaturesAMD* pGpaFeaturesAMD)
{
    bool bStatus = false;

    assert(nullptr != pGpaFeaturesAMD);

    if (nullptr != pGpaFeaturesAMD &&
        VkUtils::s_isEntryPointsInitialized &&
        nullptr != _vkGetPhysicalDeviceFeatures2KHR)
    {
        *pGpaFeaturesAMD = {};
        pGpaFeaturesAMD->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_FEATURES_AMD;

        VkPhysicalDeviceFeatures2KHR features = {};
        features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
        features.pNext = pGpaFeaturesAMD;

        _vkGetPhysicalDeviceFeatures2KHR(vkPhysicalDevice, &features);
        bStatus = true;
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }

    return bStatus;
}

bool VkUtils::GetPhysicalDeviceGpaPropertiesAMD(VkPhysicalDevice vkPhysicalDevice, VkPhysicalDeviceGpaPropertiesAMD* pGpaPropertiesAMD)
{
    bool bStatus = false;

    assert(nullptr != pGpaPropertiesAMD);

    VkPhysicalDeviceGpaFeaturesAMD gpaFeaturesAMD = {};

    if (nullptr != pGpaPropertiesAMD &&
        GetPhysicalDeviceGpaFeaturesAMD(vkPhysicalDevice, &gpaFeaturesAMD))
    {
        if (VK_TRUE == gpaFeaturesAMD.perfCounters)
        {
            // For now it is assumed that Vk MGPU support is exposed to the app
            // and the app always opens the device on the correct GPU.
            // In case where MGPU support hides the GPU from the app, then
            // we will need to use Vk MGPU extension (and possibly ADL util)
            // to get the correct HW info
            *pGpaPropertiesAMD = {};
            pGpaPropertiesAMD->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_PROPERTIES_AMD;

            VkPhysicalDeviceProperties2KHR properties = {};
            properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
            properties.pNext = pGpaPropertiesAMD;

            _vkGetPhysicalDeviceProperties2KHR(vkPhysicalDevice, &properties);

            if (pGpaPropertiesAMD->perfBlockCount > 0)
            {
                pGpaPropertiesAMD->pPerfBlocks = new(std::nothrow) VkGpaPerfBlockPropertiesAMD[pGpaPropertiesAMD->perfBlockCount];

                if (nullptr != pGpaPropertiesAMD->pPerfBlocks)
                {
                    _vkGetPhysicalDeviceProperties2KHR(vkPhysicalDevice, &properties);
                    bStatus = true;
                }
                else
                {
                    GPA_LogError("Failed to allocate memory for PerfBlocks.");
                }
            }
            else
            {
                GPA_LogError("Active physical device does not expose any perf counter blocks.");
            }
        }
        else
        {
            GPA_LogError("Active physical device does not support performance counters.");
        }
    }
    else
    {
        GPA_LogError("Failed to get physical device features.");
    }

    return bStatus;
}

void VkUtils::ReleasePhysicalDeviceGpaPropertiesAMD(VkPhysicalDeviceGpaPropertiesAMD* pGpaPropertiesAMD)
{
    if (nullptr != pGpaPropertiesAMD)
    {
        if (nullptr != pGpaPropertiesAMD->pPerfBlocks)
        {
            delete[] pGpaPropertiesAMD->pPerfBlocks;
            pGpaPropertiesAMD->pPerfBlocks = nullptr;
            pGpaPropertiesAMD->perfBlockCount = 0;
        }
    }
}

#ifdef _DEBUG
void VkUtils::DebugReportQueueFamilyTimestampBits(VkPhysicalDevice vkPhysicalDevice)
{
    if (VkUtils::s_isEntryPointsInitialized)
    {
        uint32_t queueFamilyCount = 0;
        _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, nullptr);

        if (queueFamilyCount != 0)
        {
            VkQueueFamilyProperties* pQueueFamilyProperties = new(std::nothrow) VkQueueFamilyProperties[queueFamilyCount];

            if (nullptr == pQueueFamilyProperties)
            {
                GPA_LogError("Failed to allocate memory for QueueFamilyProperties.");
            }
            else
            {
                _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, pQueueFamilyProperties);

                for (unsigned int i = 0; i < queueFamilyCount; ++i)
                {
                    if (pQueueFamilyProperties[i].timestampValidBits == 0)
                    {
                        GPA_LogError("QueueFamily Does NOT have valid timestamp bits.");
                        GPA_LogDebugMessage("QueueFamily %u does not have any valid timestamp bits; cannot support profiling.", i);
                    }
                    else
                    {
                        GPA_LogDebugMessage("QueueFamily %u has %u valid timestamp bits; it will support profiling.", i, pQueueFamilyProperties[i].timestampValidBits);
                    }
                }

                delete[] pQueueFamilyProperties;
            }
        }
        else
        {
            GPA_LogError("Device does not support any queue families; profiling cannot be supported.");
        }
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }
}
#endif //_DEBUG

bool VkUtils::IsDeviceSupportedForProfiling(VkPhysicalDevice vkPhysicalDevice)
{
    bool isSupported = false;

    if (VkUtils::s_isEntryPointsInitialized)
    {
        uint32_t queueFamilyCount = 0;
        _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, nullptr);

        if (queueFamilyCount != 0)
        {
            VkQueueFamilyProperties* pQueueFamilyProperties = new(std::nothrow) VkQueueFamilyProperties[queueFamilyCount];

            if (pQueueFamilyProperties == nullptr)
            {
                GPA_LogError("Failed to allocate memory for QueueFamilyProperties.");
            }
            else
            {
                _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, pQueueFamilyProperties);

                if (pQueueFamilyProperties[0].timestampValidBits == 0)
                {
                    GPA_LogError("QueueFamily 0 does not have any valid timestamp bits; cannot be supported.");
                }
                else
                {
                    VkPhysicalDeviceGpaFeaturesAMD featuresAMD = {};
                    featuresAMD.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_FEATURES_AMD;

                    VkPhysicalDeviceFeatures2KHR features = {};
                    features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
                    features.pNext = &featuresAMD;

                    _vkGetPhysicalDeviceFeatures2KHR(vkPhysicalDevice, &features);

                    if (featuresAMD.perfCounters == VK_TRUE)
                    {
                        isSupported = true;
                    }
                }

                delete[] pQueueFamilyProperties;
            }
        }
        else
        {
            GPA_LogError("Device does not support any queue families; cannot be supported.");
        }
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }

    return isSupported;
}

bool VkUtils::GetTimestampFrequency(VkPhysicalDevice vkPhysicalDevice, gpa_uint64& timestampFrequency)
{
    bool success = false;

    if (s_isEntryPointsInitialized)
    {
        VkPhysicalDeviceProperties properties;
        _vkGetPhysicalDeviceProperties(vkPhysicalDevice, &properties);

        // Convert timestamp period from cycles / nanosecond to cycles / second
        float timestampPeriod = properties.limits.timestampPeriod * 1000000000.0f;
        timestampFrequency = static_cast<gpa_uint64>(timestampPeriod);

        success = true;
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }

    return success;
}
<commit_msg>Fix incorrect Vulkan timestamp frequency<commit_after>//==============================================================================
// Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved.
/// \author AMD Developer Tools Team
/// \file
/// \brief  Vulkan utility functions implementation
//==============================================================================

#include <assert.h>

#include "VkUtils.h"
#include "VkEntrypoints.h"
#include "Logging.h"

bool VkUtils::GetPhysicalDeviceGpaFeaturesAMD(VkPhysicalDevice vkPhysicalDevice, VkPhysicalDeviceGpaFeaturesAMD* pGpaFeaturesAMD)
{
    bool bStatus = false;

    assert(nullptr != pGpaFeaturesAMD);

    if (nullptr != pGpaFeaturesAMD &&
        VkUtils::s_isEntryPointsInitialized &&
        nullptr != _vkGetPhysicalDeviceFeatures2KHR)
    {
        *pGpaFeaturesAMD = {};
        pGpaFeaturesAMD->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_FEATURES_AMD;

        VkPhysicalDeviceFeatures2KHR features = {};
        features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
        features.pNext = pGpaFeaturesAMD;

        _vkGetPhysicalDeviceFeatures2KHR(vkPhysicalDevice, &features);
        bStatus = true;
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }

    return bStatus;
}

bool VkUtils::GetPhysicalDeviceGpaPropertiesAMD(VkPhysicalDevice vkPhysicalDevice, VkPhysicalDeviceGpaPropertiesAMD* pGpaPropertiesAMD)
{
    bool bStatus = false;

    assert(nullptr != pGpaPropertiesAMD);

    VkPhysicalDeviceGpaFeaturesAMD gpaFeaturesAMD = {};

    if (nullptr != pGpaPropertiesAMD &&
        GetPhysicalDeviceGpaFeaturesAMD(vkPhysicalDevice, &gpaFeaturesAMD))
    {
        if (VK_TRUE == gpaFeaturesAMD.perfCounters)
        {
            // For now it is assumed that Vk MGPU support is exposed to the app
            // and the app always opens the device on the correct GPU.
            // In case where MGPU support hides the GPU from the app, then
            // we will need to use Vk MGPU extension (and possibly ADL util)
            // to get the correct HW info
            *pGpaPropertiesAMD = {};
            pGpaPropertiesAMD->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_PROPERTIES_AMD;

            VkPhysicalDeviceProperties2KHR properties = {};
            properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
            properties.pNext = pGpaPropertiesAMD;

            _vkGetPhysicalDeviceProperties2KHR(vkPhysicalDevice, &properties);

            if (pGpaPropertiesAMD->perfBlockCount > 0)
            {
                pGpaPropertiesAMD->pPerfBlocks = new(std::nothrow) VkGpaPerfBlockPropertiesAMD[pGpaPropertiesAMD->perfBlockCount];

                if (nullptr != pGpaPropertiesAMD->pPerfBlocks)
                {
                    _vkGetPhysicalDeviceProperties2KHR(vkPhysicalDevice, &properties);
                    bStatus = true;
                }
                else
                {
                    GPA_LogError("Failed to allocate memory for PerfBlocks.");
                }
            }
            else
            {
                GPA_LogError("Active physical device does not expose any perf counter blocks.");
            }
        }
        else
        {
            GPA_LogError("Active physical device does not support performance counters.");
        }
    }
    else
    {
        GPA_LogError("Failed to get physical device features.");
    }

    return bStatus;
}

void VkUtils::ReleasePhysicalDeviceGpaPropertiesAMD(VkPhysicalDeviceGpaPropertiesAMD* pGpaPropertiesAMD)
{
    if (nullptr != pGpaPropertiesAMD)
    {
        if (nullptr != pGpaPropertiesAMD->pPerfBlocks)
        {
            delete[] pGpaPropertiesAMD->pPerfBlocks;
            pGpaPropertiesAMD->pPerfBlocks = nullptr;
            pGpaPropertiesAMD->perfBlockCount = 0;
        }
    }
}

#ifdef _DEBUG
void VkUtils::DebugReportQueueFamilyTimestampBits(VkPhysicalDevice vkPhysicalDevice)
{
    if (VkUtils::s_isEntryPointsInitialized)
    {
        uint32_t queueFamilyCount = 0;
        _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, nullptr);

        if (queueFamilyCount != 0)
        {
            VkQueueFamilyProperties* pQueueFamilyProperties = new(std::nothrow) VkQueueFamilyProperties[queueFamilyCount];

            if (nullptr == pQueueFamilyProperties)
            {
                GPA_LogError("Failed to allocate memory for QueueFamilyProperties.");
            }
            else
            {
                _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, pQueueFamilyProperties);

                for (unsigned int i = 0; i < queueFamilyCount; ++i)
                {
                    if (pQueueFamilyProperties[i].timestampValidBits == 0)
                    {
                        GPA_LogError("QueueFamily Does NOT have valid timestamp bits.");
                        GPA_LogDebugMessage("QueueFamily %u does not have any valid timestamp bits; cannot support profiling.", i);
                    }
                    else
                    {
                        GPA_LogDebugMessage("QueueFamily %u has %u valid timestamp bits; it will support profiling.", i, pQueueFamilyProperties[i].timestampValidBits);
                    }
                }

                delete[] pQueueFamilyProperties;
            }
        }
        else
        {
            GPA_LogError("Device does not support any queue families; profiling cannot be supported.");
        }
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }
}
#endif //_DEBUG

bool VkUtils::IsDeviceSupportedForProfiling(VkPhysicalDevice vkPhysicalDevice)
{
    bool isSupported = false;

    if (VkUtils::s_isEntryPointsInitialized)
    {
        uint32_t queueFamilyCount = 0;
        _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, nullptr);

        if (queueFamilyCount != 0)
        {
            VkQueueFamilyProperties* pQueueFamilyProperties = new(std::nothrow) VkQueueFamilyProperties[queueFamilyCount];

            if (pQueueFamilyProperties == nullptr)
            {
                GPA_LogError("Failed to allocate memory for QueueFamilyProperties.");
            }
            else
            {
                _vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, &queueFamilyCount, pQueueFamilyProperties);

                if (pQueueFamilyProperties[0].timestampValidBits == 0)
                {
                    GPA_LogError("QueueFamily 0 does not have any valid timestamp bits; cannot be supported.");
                }
                else
                {
                    VkPhysicalDeviceGpaFeaturesAMD featuresAMD = {};
                    featuresAMD.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_FEATURES_AMD;

                    VkPhysicalDeviceFeatures2KHR features = {};
                    features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
                    features.pNext = &featuresAMD;

                    _vkGetPhysicalDeviceFeatures2KHR(vkPhysicalDevice, &features);

                    if (featuresAMD.perfCounters == VK_TRUE)
                    {
                        isSupported = true;
                    }
                }

                delete[] pQueueFamilyProperties;
            }
        }
        else
        {
            GPA_LogError("Device does not support any queue families; cannot be supported.");
        }
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }

    return isSupported;
}

bool VkUtils::GetTimestampFrequency(VkPhysicalDevice vkPhysicalDevice, gpa_uint64& timestampFrequency)
{
    bool success = false;

    if (s_isEntryPointsInitialized)
    {
        VkPhysicalDeviceProperties properties;
        _vkGetPhysicalDeviceProperties(vkPhysicalDevice, &properties);

        // Vulkan's timestampPeriod is expressed in nanoseconds per clock tick, convert to frequency in seconds
        float timestampPeriod = properties.limits.timestampPeriod;
        timestampFrequency    = static_cast<gpa_uint64>(1000000000.0f / (timestampPeriod));

        success = true;
    }
    else
    {
        GPA_LogError("Vulkan entrypoints are not initialized.");
    }

    return success;
}
<|endoftext|>