結果
| 問題 |
No.235 めぐるはめぐる (5)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2016-08-18 15:33:04 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,338 ms / 10,000 ms |
| コード長 | 7,205 bytes |
| コンパイル時間 | 2,773 ms |
| コンパイル使用メモリ | 198,148 KB |
| 実行使用メモリ | 25,728 KB |
| 最終ジャッジ日時 | 2024-11-07 19:25:43 |
| 合計ジャッジ時間 | 9,808 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 3 |
ソースコード
#include "bits/stdc++.h"
using namespace std;
#define FOR(i,j,k) for(int (i)=(j);(i)<(int)(k);++(i))
#define rep(i,j) FOR(i,0,j)
#define each(x,y) for(auto &(x):(y))
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define debug(x) cout<<#x<<": "<<(x)<<endl
#define smax(x,y) (x)=max((x),(y))
#define smin(x,y) (x)=min((x),(y))
#define MEM(x,y) memset((x),(y),sizeof (x))
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<ll> vll;
template<int MOD>
class ModInt{
public:
ModInt():value(0){}
ModInt(long long val):value((int)(val<0?MOD+val%MOD:val%MOD)){ }
ModInt& operator+=(ModInt that){
value = value+that.value;
if(value>=MOD)value-=MOD;
return *this;
}
ModInt& operator-=(ModInt that){
value -= that.value;
if(value<0)value+=MOD;
return *this;
}
ModInt& operator*=(ModInt that){
value = (int)((long long)value * that.value % MOD);
return *this;
}
ModInt &operator/=(ModInt that){
return *this *= that.inverse();
}
ModInt operator+(ModInt that) const{
return ModInt(*this)+=that;
}
ModInt operator-(ModInt that) const{
return ModInt(*this)-=that;
}
ModInt operator*(ModInt that) const{
return ModInt(*this)*=that;
}
ModInt operator/(ModInt that) const {
return ModInt(*this) /= that;
}
ModInt operator^(long long k) const{
if(value == 0)return 0;
ModInt n = *this, res = 1;
while(k){
if(k & 1)res *= n;
n *= n;
k >>= 1;
}
return res;
}
ModInt inverse() const {
long long a = value, b = MOD, u = 1, v = 0;
while(b) {
long long t = a / b;
a -= t * b;
swap(a, b);
u -= t * v;
swap(u, v);
}
return ModInt(u);
}
int toi() const{ return value; }
private:
int value;
};
typedef ModInt<1000000007> mint;
ostream& operator<<(ostream& os, const mint& x){
os << x.toi();
return os;
}
struct HLDecomposition{
vector<int> parent, depth, sub, id, head;
int cur = 0;
HLDecomposition(const vector<vector<int> > &G){
parent = depth = sub = id = head = vector<int>(G.size());
dfs(G, 0, -1, 0);
dfs2(G, 0, -1, 0);
}
int dfs(const vector<vector<int> > &G, int u, int pre, int d){
parent[u] = pre;
sub[u] = 1;
depth[u] = d;
for(int v: G[u])
if(v != pre)
sub[u] += dfs(G, v, u, d+1);
return sub[u];
}
void dfs2(const vector<vector<int> >&G, int u, int pre, int h){
head[u] = h;
id[u] = cur++;
int heavy = -1, maxi = 0;
for(int v : G[u]){
if(v != pre && maxi < sub[v]){
maxi = sub[v];
heavy = v;
}
}
if(heavy != -1)dfs2(G, heavy, u, h);
for(int v : G[u]){
if(v != pre&&v != heavy){
dfs2(G, v, u, v);
}
}
}
vector<pair<int, int> > goUpToLCA(int u, int v){
vector<pair<int, int> > res;
while(true){
if(head[u]==head[v]){
if(depth[u] > depth[v])swap(u, v);
res.emplace_back(id[u], id[v] + 1);
break;
} else{
if(depth[head[u]] > depth[head[v]])swap(u, v);
res.emplace_back(id[head[v]], id[v] + 1);
v = parent[head[v]];
}
}
return res;
}
};
vector<mint> sumC;
bool init = true;
struct LazySegTreeSum{
int dataSize;
vector<mint> value, lazy;
LazySegTreeSum(int n){
dataSize = 1;
while(dataSize < n)dataSize *= 2;
int treeSize = 2 * dataSize;
value = lazy = vector<mint>(treeSize);
}
void propagate(int index, int curL, int curR){
// 自分の値をlazyにもとづいて書き換えて自分のlazyをクリア。
if(lazy[index].toi()){
int left = index * 2 + 1, right = index * 2 + 2;
if(!init)value[index] += lazy[index] * (sumC[curR]-sumC[curL]);
else value[index] += lazy[index] * (curR - curL);
// 子のlazyを書き換える。
if(curR - curL > 1){
lazy[left] += lazy[index];
lazy[right] += lazy[index];
}
lazy[index] = 0;
}
}
// [curL, curR) を評価する
void update(int index, int curL, int curR, int givenL, int givenR, int x){
// 範囲外であろうとpropagateは必ず呼ぶ。そうでないと、親がうまく評価されない
propagate(index, curL, curR);
// 範囲外
if(curR <= givenL || givenR <= curL)return;
if(givenL <= curL && curR <= givenR){
// 直接書き換えないでindexのlazyを書き換えてpropagateを呼ぶ
lazy[index] += x;
propagate(index, curL, curR);
} else{
int mid = (curL + curR) / 2;
update(index * 2 + 1, curL, mid, givenL, givenR, x);
update(index * 2 + 2, mid, curR, givenL, givenR, x);
value[index] = value[index * 2 + 1] + value[index * 2 + 2];
}
}
void update(int l, int r, int x){
update(0, 0, dataSize, l, r, x);
}
mint query(int l, int r){
return query(0, 0, dataSize, l, r);
}
mint query(int index, int curL, int curR, int givenL, int givenR){
// 範囲外
if(curR <= givenL || givenR <= curL)return 0;
propagate(index, curL, curR);
if(givenL <= curL && curR <= givenR){
return value[index];
} else{
int mid = (curL + curR) / 2;
mint resL = query(index * 2 + 1, curL, mid, givenL, givenR);
mint resR = query(index * 2 + 2, mid, curR, givenL, givenR);
return resL + resR;
}
}
};
int main(){
int N;
cin >> N;
vi S(N), C(N);
rep(i, N)scanf("%d", &S[i]);
rep(i, N)scanf("%d", &C[i]);
vector<vi> G(N);
rep(i, N-1){
int a, b;
scanf("%d%d", &a, &b);
--a; --b;
G[a].push_back(b);
G[b].push_back(a);
}
auto hlc = HLDecomposition(G);
LazySegTreeSum st(N);
int M = st.dataSize;
sumC = vector<mint>(M+1);
rep(i, N){
int u = hlc.id[i];
st.update(u, u + 1, S[i]);
sumC[u+1] = C[i];
}
rep(i, M)sumC[i + 1] += sumC[i];
init = false;
int Q;
cin >> Q;
while(Q--){
int q, x, y;
scanf("%d%d%d", &q, &x, &y);
--x;
--y;
if(q == 0){
int z;
scanf("%d", &z);
auto segs = hlc.goUpToLCA(x, y);
each(seg, segs){
st.update(seg.first, seg.second, z);
}
} else{
mint ans;
auto segs = hlc.goUpToLCA(x, y);
each(seg, segs){
ans += st.query(seg.first, seg.second);
}
printf("%d\n", ans.toi());
}
}
}