結果
問題 | No.235 めぐるはめぐる (5) |
ユーザー | paruki |
提出日時 | 2016-08-18 15:33:04 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.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 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1,338 ms
25,088 KB |
testcase_01 | AC | 842 ms
25,728 KB |
testcase_02 | AC | 1,246 ms
25,216 KB |
ソースコード
#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()); } } }