結果
| 問題 |
No.235 めぐるはめぐる (5)
|
| コンテスト | |
| ユーザー |
noshi_bot
|
| 提出日時 | 2018-06-16 17:57:38 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 903 ms / 10,000 ms |
| コード長 | 8,505 bytes |
| コンパイル時間 | 829 ms |
| コンパイル使用メモリ | 69,464 KB |
| 実行使用メモリ | 20,128 KB |
| 最終ジャッジ日時 | 2024-06-30 16:19:02 |
| 合計ジャッジ時間 | 4,640 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 3 |
ソースコード
#include <cassert>
#include <cstddef>
#include <memory>
#include <utility>
#include <vector>
template <class ValueMonoid, class OperatorMonoid, class Modifier>
class link_cut_tree {
public:
using value_structure = ValueMonoid;
using value_type = typename value_structure::value_type;
using operator_structure = OperatorMonoid;
using operator_type = typename operator_structure::value_type;
using modifier_type = Modifier;
using size_type = ::std::size_t;
private:
class node_type {
public:
node_type *left, *right, *parent;
typename link_cut_tree::value_type value, sum;
typename link_cut_tree::operator_type lazy;
bool reversed; // reverse->lazy
node_type(value_type &&v, operator_type &&o)
: value(::std::move(v)), sum(value), lazy(::std::move(o)), reversed(0) {
}
};
using pointer = node_type *;
using const_pointer = const node_type *;
::std::vector<node_type> nodes;
size_type size_;
value_structure vf;
operator_structure of;
modifier_type mf;
pointer nil() noexcept { return nodes.data(); }
void reverse(const pointer ptr) {
ptr->lazy = of.reverse(ptr->lazy);
ptr->reversed ^= 1;
}
void push(const pointer ptr) {
if (ptr->reversed) {
ptr->reversed = 0;
ptr->value = vf.reverse(ptr->value);
::std::swap(ptr->left, ptr->right);
reverse(ptr->left);
reverse(ptr->right);
}
ptr->left->lazy = of(ptr->left->lazy, ptr->lazy);
ptr->right->lazy = of(ptr->right->lazy, ptr->lazy);
ptr->value = mf(ptr->value, ptr->lazy);
ptr->lazy = of.identity();
}
void propagate(pointer ptr) {
pointer prev = nullptr;
while (ptr != nil()) {
::std::swap(ptr->parent, prev);
::std::swap(ptr, prev);
}
while (prev) {
push(prev);
::std::swap(prev->parent, ptr);
::std::swap(prev, ptr);
}
nil()->sum = vf.identity();
nil()->lazy = of.identity();
nil()->reversed = 0;
}
value_type reflect(const const_pointer ptr) {
return mf(ptr->reversed ? vf.reverse(ptr->sum) : ptr->sum, ptr->lazy);
}
void calc(const pointer ptr) {
ptr->sum = vf(vf(reflect(ptr->left), ptr->value), reflect(ptr->right));
}
static void set_l(const pointer ptr, const pointer ch) {
ptr->left = ch;
ch->parent = ptr;
}
static void set_r(const pointer ptr, const pointer ch) {
ptr->right = ch;
ch->parent = ptr;
}
void rotate_l(const pointer ptr, const pointer ch) {
set_r(ptr, ch->left);
calc(ptr);
set_l(ch, ptr);
}
void rotate_r(const pointer ptr, const pointer ch) {
set_l(ptr, ch->right);
calc(ptr);
set_r(ch, ptr);
}
void splay(const pointer ptr) {
for (pointer x, y = ptr;;) {
x = ptr->parent;
if (x->left == y) {
y = x->parent;
ptr->parent = y->parent;
if (y->left == x)
rotate_r(y, x), rotate_r(x, ptr);
else if (y->right == x)
rotate_l(y, ptr), rotate_r(x, ptr);
else
return ptr->parent=y,rotate_r(x, ptr);
}
else if (x->right == y) {
y = x->parent;
ptr->parent = y->parent;
if (y->right == x)
rotate_l(y, x), rotate_l(x, ptr);
else if (y->left == x)
rotate_r(y, ptr), rotate_l(x, ptr);
else
return ptr->parent = y, rotate_l(x, ptr);
}
else {
return;
}
}
}
void expose(const pointer ptr) {
propagate(ptr);
pointer x = ptr, prev = nil();
while (x != nil()) {
splay(x);
x->right = prev;
calc(x);
prev = x;
x = x->parent;
}
splay(ptr);
calc(ptr);
}
void reroot(const pointer ptr) {
expose(ptr);
reverse(ptr);
}
pointer get_ptr(const size_type i) noexcept { return nodes.data() + 1 + i; }
public:
link_cut_tree() : link_cut_tree(0) {}
explicit link_cut_tree(const size_type size,
const value_structure &x = value_structure(),
const operator_structure &y = operator_structure(),
const modifier_type &z = modifier_type())
: size_(size), vf(x), of(y), mf(z) {
nodes.reserve(size_ + 1);
nodes.emplace_back(vf.identity(), of.identity());
const pointer n = nil();
n->left = n->right = n->parent = n;
nodes.resize(size_ + 1, nodes.front());
}
bool empty() const noexcept { return !size_; }
size_type size() const noexcept { return size_; }
bool connected(const size_type v, const size_type u) {
assert(v < size());
assert(u < size());
expose(get_ptr(v));
expose(get_ptr(u));
return nodes[v + 1].parent != nil() || v == u;
}
value_type fold(const size_type v, const size_type u) {
assert(v < size());
assert(u < size());
assert(connected(v, u));
reroot(get_ptr(v));
expose(get_ptr(u));
return nodes[u + 1].sum;
}
void link(const size_type parent, const size_type child) {
assert(parent < size());
assert(child < size());
assert(!connected(parent, child));
reroot(get_ptr(child));
nodes[child + 1].parent = get_ptr(parent);
}
void cut(const size_type v) {
assert(v < size());
expose(get_ptr(v));
nodes[v + 1].left->parent = nil();
nodes[v + 1].left = nil();
nodes[v + 1].sum = nodes[v + 1].value;
}
void update(const size_type v, const size_type u, const operator_type &data) {
assert(v < size());
assert(u < size());
assert(connected(v, u));
reroot(get_ptr(v));
expose(get_ptr(u));
nodes[u + 1].lazy = data;
}
template<class F>
void update(const size_type v, const F &f) {
assert(v < size());
expose(get_ptr(v));
nodes[v + 1].value = f(nodes[v + 1].value);
calc(get_ptr(v));
}
};
#include<cstdint>
template<std::uint_fast32_t MODULO>
struct modint {
private:
using uint32 = std::uint_fast32_t;
using uint64 = std::uint_fast64_t;
public:
uint32 a;
modint() :a(0) {}
modint(const std::int_fast64_t &x) :a(set(x%MODULO + MODULO)) {}
static uint32 set(const uint32 &x) { return(x<MODULO) ? x : x - MODULO; }
static modint make(const uint32 &x) { modint ret;ret.a = x;return ret; }
modint operator+(const modint &o)const { return make(set(a + o.a)); }
modint operator-(const modint &o)const { return make(set(a + MODULO - o.a)); }
modint operator*(const modint &o)const { return make((uint64)a*o.a%MODULO); }
modint operator/(const modint &o)const { return make((uint64)a*~o%MODULO); }
modint &operator+=(const modint &o) { return *this = *this + o; }
modint &operator-=(const modint &o) { return *this = *this - o; }
modint &operator*=(const modint &o) { return *this = *this * o; }
modint &operator/=(const modint &o) { return *this = *this / o; }
modint &operator^=(const uint32 &o) { return *this = *this^o; }
modint operator~ ()const { return *this ^ (MODULO - 2); }
modint operator- ()const { return make(set(MODULO - a)); }
modint operator++() { return *this = make(set(a + 1)); }
modint operator--() { return *this = make(set(a + MODULO - 1)); }
bool operator==(const modint &o)const { return a == o.a; }
bool operator!=(const modint &o)const { return a != o.a; }
bool operator< (const modint &o)const { return a < o.a; }
bool operator<=(const modint &o)const { return a <= o.a; }
bool operator> (const modint &o)const { return a > o.a; }
bool operator>=(const modint &o)const { return a >= o.a; }
explicit operator bool()const { return a; }
explicit operator uint32()const { return a; }
modint operator^(uint32 x)const {
uint64 t = a, u = 1;
while (x) { if (x & 1) u = u*t%MODULO;t = (t*t) % MODULO;x >>= 1; }
return make(u);
}
};
using mint = modint<1000000007>;
struct city{
using value_type = std::pair<mint, mint>;
using cref = const value_type &;
value_type operator()(cref x, cref y)const {
return { x.first + y.first,x.second + y.second };
}
value_type identity()const {
return { 0,0 };
}
value_type reverse(cref x)const {
return x;
}
};
struct parade {
using value_type = mint;
mint operator()(mint x, mint y)const {
return x + y;
}
mint identity()const {
return 0;
}
mint reverse(mint x)const {
return x;
}
};
struct act {
std::pair<mint, mint> operator()(const std::pair<mint, mint> &x, mint y)const {
return { x.first + x.second*y,x.second };
}
};
#include <cstdio>
int main() {
using P = std::pair<mint, mint>;
int n;
scanf("%d", &n);
link_cut_tree<city, parade, act> T(n);
std::vector<mint> s(n), c(n);
for (auto &e : s)
scanf("%u", &e.a);
for (auto &e : c)
scanf("%u", &e.a);
for (int i = 0;i < n;++i)
T.update(i, [&](const P&x) {return P(s[i], c[i]);});
while(--n) {
int a, b;
scanf("%d%d", &a, &b);
--a;--b;
T.link(a, b);
}
int q;
scanf("%d", &q);
while(q--) {
int t, x, y;
mint z;
scanf("%d%d%d", &t, &x, &y);
--x;--y;
if (t) {
printf("%u\n", T.fold(x, y).first.a);
}
else {
scanf("%u", &z.a);
T.update(x, y, mint(z));
}
}
return 0;
}
noshi_bot