結果
| 問題 |
No.235 めぐるはめぐる (5)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2019-05-02 20:53:07 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 8,945 bytes |
| コンパイル時間 | 2,256 ms |
| コンパイル使用メモリ | 139,128 KB |
| 実行使用メモリ | 49,728 KB |
| 最終ジャッジ日時 | 2024-12-31 13:39:54 |
| 合計ジャッジ時間 | 11,445 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 2 WA * 1 |
ソースコード
#define _USE_MATH_DEFINES
#include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <complex>
#include <string>
#include <vector>
#include <array>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
#include <iterator>
#include <memory>
#include <regex>
using namespace std;
const int MOD = 1000000007;
class DelayExec
{
public:
using T1 = pair<long long, long long>;
using T2 = long long;
// データの初期値、以下の条件を満たすこと
// uniteData(v, INIT_DATA) == v
static const T1 INIT_DATA;
// 遅延の初期値、以下の条件を満たすこと
// updateData(prev, size, INIT_DELAY) == prev
// updateDelay(x, INIT_DELAY) == x
static const T2 INIT_DELAY;
// 2つの区間の計算結果v1,v2に対して、
// その2つの区間を統合した区間における計算結果を返す
static T1 uniteData(T1 v1, T1 v2){
v1.first += v2.first;
v1.first %= MOD;
v1.second += v2.second;
v2.second %= MOD;
return v1;
}
// 長さがlenの区間における前回の計算結果prevに対して、
// 区間の各要素にパラメータxを用いた更新処理を適用した後の計算結果を返す
static T1 updateData(T1 prev, int len, T2 x){
prev.first += prev.second * x;
prev.first %= MOD;
return prev;
}
// パラメータx1,x2による2つの更新処理を順に適用した場合に対して、
// 同じ結果になるような1つの更新処理のパラメータを返す
static T2 updateDelay(T2 x1, T2 x2){
return (x1 + x2) % MOD;
}
};
const DelayExec::T1 DelayExec::INIT_DATA = make_pair(0, 0);
const DelayExec::T2 DelayExec::INIT_DELAY = 0;
template <class D = DelayExec>
class SegmentTree
{
private:
using T1 = typename D::T1;
using T2 = typename D::T2;
int n;
vector<T1> data;
vector<T2> delay;
void updateTree(int a, int b, int k, int l, int r, T2 x){
if(a <= l && r <= b){
data[k] = D::updateData(data[k], r - l, x);
delay[k] = D::updateDelay(delay[k], x);
}
else if(a < r && l < b){
int len = (r - l) / 2;
for(int i=0; i<2; ++i){
data[k*2+1+i] = D::updateData(data[k*2+1+i], len, delay[k]);
delay[k*2+1+i] = D::updateDelay(delay[k*2+1+i], delay[k]);
}
delay[k] = D::INIT_DELAY;
updateTree(a, b, k*2+1, l, (l+r+1)/2, x);
updateTree(a, b, k*2+2, (l+r+1)/2, r, x);
data[k] = D::uniteData(data[k*2+1], data[k*2+2]);
}
}
T1 getValue(int a, int b, int k, int l, int r){
if(a <= l && r <= b){
return data[k];
}
else if(a < r && l < b){
int len = (r - l) / 2;
for(int i=0; i<2; ++i){
data[k*2+1+i] = D::updateData(data[k*2+1+i], len, delay[k]);
delay[k*2+1+i] = D::updateDelay(delay[k*2+1+i], delay[k]);
}
delay[k] = D::INIT_DELAY;
T1 v1 = getValue(a, b, k*2+1, l, (l+r+1)/2);
T1 v2 = getValue(a, b, k*2+2, (l+r+1)/2, r);
return D::uniteData(v1, v2);
}
else{
return D::INIT_DATA;
}
}
public:
SegmentTree(int n0){
n = 1;
while(n < n0)
n *= 2;
data.assign(2*n-1, D::INIT_DATA);
delay.assign(2*n-1, D::INIT_DELAY);
}
SegmentTree(const vector<T1>& v) : SegmentTree((int)v.size()){
for(unsigned i=0; i<v.size(); ++i)
data[n-1+i] = v[i];
for(int k=n-2; k>=0; --k)
data[k] = D::uniteData(data[k*2+1], data[k*2+2]);
}
// 区間[a,b)の要素にパラメータxによる更新処理を適用
void update(int a, int b, T2 x){
updateTree(a, b, 0, 0, n, x);
}
// 区間[a,b)の計算結果を返す
T1 get(int a, int b){
return getValue(a, b, 0, 0, n);
}
// a番目の要素をxで上書きする
void set(int a, T1 x){
getValue(a, a+1, 0, 0, n);
data[n-1+a] = x;
updateTree(a, a+1, 0, 0, n, D::INIT_DELAY);
}
};
template <class D = DelayExec>
class HeavyLightDecomposition
{
private:
using T1 = typename D::T1;
using T2 = typename D::T2;
vector<int> size, depth, parent, top, index;
SegmentTree<D> data;
// 2回の深さ優先探索によりHL分解を行う
void dfs1(const vector<vector<int> >& edges, int curr, int prev)
{
size[curr] = 1;
for(int next : edges[curr]){
if(next == prev)
continue;
dfs1(edges, next, curr);
size[curr] += size[next];
}
}
void dfs2(const vector<vector<int> >& edges, int curr, int prev, int top2, int& cnt)
{
index[curr] = cnt;
++ cnt;
top[index[curr]] = index[top2];
if(prev != -1){
depth[index[curr]] = depth[index[prev]] + 1;
parent[index[curr]] = index[prev];
}
int maxSize = 0;
int next = -1;
for(int to : edges[curr]){
if(to != prev && maxSize < size[to]){
maxSize = size[to];
next = to;
}
}
if(next != -1)
dfs2(edges, next, curr, top2, cnt);
for(int to : edges[curr]){
if(to != prev && to != next)
dfs2(edges, to, curr, to, cnt);
}
}
public:
// コンストラクタ
HeavyLightDecomposition(const vector<vector<int> >& edges, int root) : data(0)
{
int n = edges.size();
int cnt = 0;
size.resize(n);
top.resize(n);
index.resize(n);
depth.assign(n, 0);
parent.assign(n, -1);
dfs1(edges, root, -1);
dfs2(edges, root, -1, root, cnt);
vector<int> size2(n);
for(int i=0; i<n; ++i)
size2[index[i]] = size[i];
size = move(size2);
data = SegmentTree<D>(n);
}
// コンストラクタ(初期値あり)
HeavyLightDecomposition(const vector<vector<int> >& edges, int root, const vector<T1>& init) : HeavyLightDecomposition(edges, root)
{
int n = edges.size();
vector<T1> v(n);
for(int i=0; i<n; ++i)
v[index[i]] = init[i];
data = SegmentTree<D>(v);
}
// a,b間のパスに対してパラメータxによる更新を適用
void updatePath(int a, int b, T2 x){
a = index[a];
b = index[b];
while(top[a] != top[b]){
int a2 = top[a];
int b2 = top[b];
if(depth[a2] < depth[b2]){
swap(a, b);
swap(a2, b2);
}
data.update(a2, a+1, x);
a = parent[a2];
}
if(depth[a] > depth[b])
swap(a, b);
data.update(a, b+1, x);
}
// a,b間のパスの結果を取得
T1 getPath(int a, int b){
a = index[a];
b = index[b];
T1 ans = D::INIT_DATA;
while(top[a] != top[b]){
int a2 = top[a];
int b2 = top[b];
if(depth[a2] < depth[b2]){
swap(a, b);
swap(a2, b2);
}
ans = D::uniteData(ans, data.get(a2, a+1));
a = parent[a2];
}
if(depth[a] > depth[b])
swap(a, b);
ans = D::uniteData(ans, data.get(a, b+1));
return ans;
}
// aを根とする部分木に対してパラメータxによる更新を適用
void updateSubTree(int a, T2 x){
a = index[a];
data.update(a, a+size[a], x);
}
// aを根とする部分木の結果を取得
T1 getSubTree(int a){
a = index[a];
return data.get(a, a+size[a]);
}
// 部分木のサイズを取得
int getSize(int a){
a = index[a];
return size[a];
}
};
int main()
{
int n;
cin >> n;
vector<pair<long long, long long> > v(n);
for(int i=0; i<n; ++i)
cin >> v[i].first;
for(int i=0; i<n; ++i)
cin >> v[i].second;
vector<vector<int> > edges(n);
for(int i=0; i<n-1; ++i){
int a, b;
cin >> a >> b;
-- a;
-- b;
edges[a].push_back(b);
edges[b].push_back(a);
}
int q;
cin >> q;
HeavyLightDecomposition<> hld(edges, 0, v);
while(--q >= 0){
int t, x, y;
cin >> t >> x >> y;
-- x;
-- y;
if(t == 0){
long long z;
cin >> z;
hld.updatePath(x, y, z);
}
else{
cout << hld.getPath(x, y).first << endl;
}
}
return 0;
}