結果
| 問題 |
No.235 めぐるはめぐる (5)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2018-06-04 16:56:10 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 8,441 bytes |
| コンパイル時間 | 2,211 ms |
| コンパイル使用メモリ | 188,104 KB |
| 実行使用メモリ | 75,868 KB |
| 最終ジャッジ日時 | 2024-06-30 09:43:23 |
| 合計ジャッジ時間 | 8,891 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | WA * 3 |
ソースコード
#include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 1000000007
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto& (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define spair(p) cout<<#p<<": "<<p.fi<<" "<<p.se<<endl
#define sar(a,n) cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl
#define svec(v) cout<<#v<<":";rep(pachico,v.size())cout<<" "<<v[pachico];cout<<endl
#define svecp(v) cout<<#v<<":";each(pachico,v)cout<<" {"<<pachico.first<<":"<<pachico.second<<"}";cout<<endl
#define sset(s) cout<<#s<<":";each(pachico,s)cout<<" "<<pachico;cout<<endl
#define smap(m) cout<<#m<<":";each(pachico,m)cout<<" {"<<pachico.first<<":"<<pachico.second<<"}";cout<<endl
using namespace std;
typedef pair<int,int> P;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<P> vp;
typedef vector<string> vs;
const int MAX_N = 200005;
inline int add(int x,int y)
{
return (x + y)%MOD;
}
inline int sub(int x,int y)
{
return (x+MOD-y)%MOD;
}
inline int mul(int x,int y)
{
return (ll)x*y%MOD;
}
int s[MAX_N],c[MAX_N];
template<typename T> class RootedCentroidDecomposition
{
public:
struct edge {
int to; T cost;
};
int V, LOGV, CentroidRoot;
vector<vector<edge> > G;
vector<vector<int> > TreeID, centroid, parent;
vector<vector<T> > height;
vector<bool> used;
vector<int> depth, stsize;
vector<T> constant, init, gap, plus;
void FirstDFS(int u, int par, int dep, T val, T val2){
init[u] = val;
constant[u] = val2, parent[0][u] = par;
depth[u] = dep, stsize[u] = 1;
for(auto& e : G[u]){
if(!used[e.to] && e.to != par){
e.cost = c[e.to-1];
FirstDFS(e.to, u, dep + 1, add(val, e.cost), add(val2, s[e.to-1]));
stsize[u] += stsize[e.to];
}
}
}
void CalcSize(int u, int par){
stsize[u] = 1;
for(auto& e : G[u]){
if(!used[e.to] && e.to != par){
CalcSize(e.to, u);
stsize[u] += stsize[e.to];
}
}
}
void CalcRootHeight(int u, int par, const int cent, const int dep, T val){
TreeID[dep][u] = 0, height[dep][u] = val;
for(auto& e : G[u]){
if(!used[e.to] && e.to != par){
if(TreeID[dep][e.to] == 0){
CalcRootHeight(e.to, u, cent, dep, add(val, e.cost));
}else{
CalcRootHeight(e.to, u, cent, dep, val);
}
}
}
}
void CalcHeight(int u, int par, const int ID, const int dep, const T val){
TreeID[dep][u] = ID, height[dep][u] = val;
for(auto& e : G[u]){
if(!used[e.to] && e.to != par){
CalcHeight(e.to, u, ID, dep, val);
}
}
}
void RecBuild(int r, int par, int ID, int dep){
if(par < 0){
FirstDFS(r, -1, 0, 0, 0);
}else{
CalcSize(r, -1);
}
int sz = stsize[r], p = -1;
bool ok = false;
int cent = r;
while(!ok){
ok = true;
for(auto& e : G[cent]){
if(!used[e.to] && e.to != p && 2*stsize[e.to] > sz){
p = cent, cent = e.to, ok = false;
break;
}
}
}
if(par >= 0){
centroid[par][ID] = cent;
}else{
CentroidRoot = cent;
}
// cout << r << " " << cent << endl;
int nwnode = cent;
while(nwnode != r){
TreeID[dep][nwnode] = 0;
nwnode = parent[0][nwnode];
}
used[cent] = true;
T diff = ID?sub(init[r], init[parent[0][r]]):0;
height[dep][cent] = add(sub(init[cent], init[r]), diff);
int childID = 1;
for(auto& e : G[cent]){
if(!used[e.to]){
if(e.to == parent[0][cent]){
CalcRootHeight(r, -1, cent, dep, diff);
}else{
CalcHeight(e.to, -1, childID++, dep, height[dep][cent]);
}
}
}
centroid[cent].resize(childID, -1);
childID = 1;
// show("START");
for(auto& e : G[cent]){
// cout << cent << " " << e.to << " " << e.cost << endl;
if(!used[e.to]){
if(e.to == parent[0][cent]){
// show(r);
RecBuild(r, cent, 0, dep+1);
}else{
RecBuild(e.to, cent, childID++, dep+1);
}
}
}
}
int LCA(int u, int v){
if(depth[u] > depth[v]) swap(u,v);
for(int i = 0; i < LOGV; i++){
if((depth[v] - depth[u]) & (1 << i)){
v = parent[i][v];
}
}
if(u == v) return u;
for(int i = LOGV - 1; i >= 0; i--){
if(parent[i][u] != parent[i][v]){
u = parent[i][u], v = parent[i][v];
}
}
return parent[0][u];
}
void Range(const int u, int cent, int dep, const T val){
gap[cent] = add(gap[cent], mul(val, height[dep][u]));
int NextID = TreeID[dep][u];
if(NextID < 0) return;
if(NextID != 0){
plus[cent] = add(plus[cent], val);
}
if(u != cent){
Range(u, centroid[cent][NextID], dep + 1, val);
}
}
T Query(const int u, int dep, int cent){
if(u == cent) return add(gap[cent], constant[u]);
int NextID = TreeID[dep][u];
if(NextID < 0){
return constant[u];
}
if(NextID == 0){
return add(mul(plus[cent], height[dep][u]), Query(u, dep + 1, centroid[cent][NextID]));
}else{
return add(gap[cent], Query(u, dep + 1, centroid[cent][NextID]));
}
}
public:
RootedCentroidDecomposition(const int node_size) : V(node_size), LOGV(ceil(log2(V))), CentroidRoot(-1),
G(V), TreeID(LOGV, vector<int>(V, -1)), centroid(V), parent(LOGV, vector<int>(V, -1)),
height(LOGV, vector<T>(V, 0)), used(V, false), depth(V, 0), stsize(V, 0), constant(V, 0),
init(V, 0), gap(V, 0), plus(V, 0){}
void add_edge(const int u, const int v, const T cost){
G[u].push_back((edge){v, cost}),G[v].push_back((edge){u, cost});
}
void build(){
RecBuild(0, -1, 0, 0);
for(int i = 0; i < LOGV - 1; i++){
for(int j = 0; j < V; j++){
if(parent[i][j] >= 0){
parent[i+1][j] = parent[i][parent[i][j]];
}
}
}
}
void range(int u, int v, const T val){
if(u == v) return;
int lca = LCA(u, v);
Range(u, CentroidRoot, 0, val), Range(v, CentroidRoot, 0, val);
Range(lca, CentroidRoot, 0, MOD-val), Range(parent[0][lca], CentroidRoot, 0, MOD-val);
}
T query(int u, int v){
if(u == v) return 0;
T r1 = Query(u, 0, CentroidRoot), r2 = Query(v, 0, CentroidRoot);
int lca = LCA(u, v);
T r3 = Query(lca, 0, CentroidRoot), r4 = Query(parent[0][lca], 0, CentroidRoot);
// cout << r1 << " " << r2 << " " << r3 << " " << r4 << "\n";
return r1 + r2 - r3 - r4;
}
};
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
int n;
cin >> n;
rep(i,n){
cin >> s[i];
}
rep(i,n){
cin >> c[i];
}
RootedCentroidDecomposition<int> rcd(n+1);
rcd.add_edge(0, 1, 0);
rep(i,n-1){
int a,b;
cin >> a >> b;
rcd.add_edge(a, b, 0);
}
rcd.build();
int q;
cin >> q;
rep(i,q){
int a;
cin >> a;
if(a == 0){
int b,c,d;
cin >> b >> c >> d;
rcd.range(b, c, d);
}else{
int b,c;
cin >> b >> c;
cout << rcd.query(b, c) << "\n";
}
}
return 0;
}