結果
問題 | No.235 めぐるはめぐる (5) |
ユーザー | koyumeishi |
提出日時 | 2015-06-27 01:52:40 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 1,069 ms / 10,000 ms |
コード長 | 9,775 bytes |
コンパイル時間 | 1,279 ms |
コンパイル使用メモリ | 109,016 KB |
実行使用メモリ | 98,000 KB |
最終ジャッジ日時 | 2024-07-07 19:51:31 |
合計ジャッジ時間 | 5,572 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1,069 ms
89,728 KB |
testcase_01 | AC | 577 ms
98,000 KB |
testcase_02 | AC | 863 ms
91,344 KB |
コンパイルメッセージ
main.cpp: In function ‘int main()’: main.cpp:465:25: warning: format ‘%d’ expects argument of type ‘int*’, but argument 2 has type ‘__gnu_cxx::__alloc_traits<std::allocator<long long int>, long long int>::value_type*’ {aka ‘long long int*’} [-Wformat=] 465 | scanf("%d", &s[i]); | ~^ | | | int* | %lld main.cpp:469:25: warning: format ‘%d’ expects argument of type ‘int*’, but argument 2 has type ‘__gnu_cxx::__alloc_traits<std::allocator<long long int>, long long int>::value_type*’ {aka ‘long long int*’} [-Wformat=] 469 | scanf("%d", &c[i]); | ~^ | | | int* | %lld main.cpp:461:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 461 | scanf("%d", &n); | ~~~~~^~~~~~~~~~ main.cpp:465:22: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 465 | scanf("%d", &s[i]); | ~~~~~^~~~~~~~~~~~~ main.cpp:469:22: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 469 | scanf("%d", &c[i]); | ~~~~~^~~~~~~~~~~~~ main.cpp:475:22: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 475 | scanf("%d%d", &a,&b); | ~~~~~^~~~~~~~~~~~~~~ main.cpp:484:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 484 | scanf("%d", &q);
ソースコード
#include <iostream> #include <vector> #include <cstdio> #include <sstream> #include <map> #include <string> #include <algorithm> #include <queue> #include <cmath> #include <set> using namespace std; #define MOD 1000000007 vector<long long> s, c; class LCA{ int root; //depth of node[i] vector<int> d; //parent of node[i] vector<vector<int> > p; int log_n; //initialization of depths and parents void init(vector<vector<int> > &g, int pos, int last, int v){ d[pos] = v; p[0][pos] = last; for(int i=0; i<g[pos].size(); i++){ if(g[pos][i] == last) continue; init(g, g[pos][i], pos, v+1); } } public: //vector<vector<int> > //g[i][j] := node[i]'s edge gose to node[ g[i][j] ] LCA(vector<vector<int> > &g, int r){ int n = g.size(); root = r; d = vector<int>(n); log_n = 1; while(1LL<<log_n <= n) log_n++; p = vector<vector<int> >(log_n, vector<int>(n)); init(g, root,-1,0); for(int k=0; k+1 < log_n; k++){ for(int v=0; v<n; v++){ if(p[k][v] < 0) p[k+1][v] = -1; else p[k+1][v] = p[k][p[k][v]]; } } } LCA(vector<vector<int> > &g){ int n = g.size(); root = 0; d = vector<int>(n); log_n = 1; while(1LL<<log_n <= n) log_n++; p = vector<vector<int> >(log_n, vector<int>(n)); //initialize as root = 0 init(g, root,-1,0); for(int k=0; k+1 < log_n; k++){ for(int v=0; v<n; v++){ if(p[k][v] < 0) p[k+1][v] = -1; else p[k+1][v] = p[k][p[k][v]]; } } } //return the node number of lowest common ancestor between u and v int get_lca(int u, int v){ if(d[u] > d[v]) swap(u,v); for(int k=0; k<log_n; k++){ if( (d[v] - d[u]) >> k & 1){ v = p[k][v]; } } if(u==v) return u; for(int k=log_n-1; k>=0; k--){ if(p[k][u] != p[k][v]) { u = p[k][u]; v = p[k][v]; } } return p[0][u]; } //return depth of node[u] int depth(int u){ return d[u]; } }; struct my_value{ long long c; long long val; my_value(): c(0), val(0){ } my_value(long long c_, long long val_) : c(c_), val(val_){ } }; template<class T=my_value, class V=long long> class Segment_Tree_Lazy{ private: //default values are set in the constractor const T default_value; //default (NULL) node value const V default_lazy_value; //default lazy value struct node{ T value; V lazy_value; bool lazy; int lb; int ub; node* par; node* lch; node* rch; node(T default_value, V default_lazy_value) : value(default_value), lazy_value(default_lazy_value), lazy(false), lb(0),ub(0), par(NULL),lch(NULL),rch(NULL){ } }; T evaluate(T left_val, T right_val){ return my_value((left_val.c + right_val.c)%MOD, (left_val.val + right_val.val)%MOD); } void new_lazy(node* t, V z){ if(t==NULL) return; if(t->lazy){ t->lazy_value = (t->lazy_value + z)%MOD; }else{ t->lazy_value = z; } t->lazy = true; } T get_value(node* t){ if(t==NULL) return default_value; if(t->lazy) return T(t->value.c , (t->value.val + (t->lazy_value * t->value.c)%MOD) % MOD); return t->value; } vector<node> v; node* root; int size; node* constract(node* t, int pos, int lb, int ub){ if(pos == 0){ t->par = t; } t->lb = lb; t->ub = ub; if(pos<size-1){ t->lch = constract(&v[(pos<<1) + 1], (pos<<1) + 1, lb, (ub+lb)>>1); t->lch->par = t; t->rch = constract(&v[(pos<<1) + 2], (pos<<1) + 2, (ub+lb)>>1, ub); t->rch->par = t; } return t; } void initialize(int size_){ size = 1; while(size < size_) size <<= 1; v = vector<node>(size<<1, node(default_value, default_lazy_value)); root = constract(&v[0], 0, 0, size); } //propagate lazy value of node t to its children void push(node* t){ if(t==NULL) return; if(t->lazy){ if(t->lch != NULL){ //has child new_lazy(t->lch, t->lazy_value); new_lazy(t->rch, t->lazy_value); t->value = evaluate( get_value(t->lch), get_value(t->rch) ); }else{ t->value = get_value(t); } t->lazy_value = default_lazy_value; t->lazy = false; } } void range_add(int left, int right, V z, node* t){ if(t==NULL) return; if(t->ub <= left || right <= t->lb){ return; } push(t); if(left <= t->lb && t->ub <= right){ new_lazy(t, z); return; } //partialy covered range_add(left, right, z, t->lch); range_add(left, right, z, t->rch); t->value = evaluate( get_value(t->lch), get_value(t->rch) ); } //get value of [left,right) T get_range_value(int left, int right, node* t){ if(t==NULL) return default_value; if(t->ub <= left || right <= t->lb){ return default_value; } push(t); if(left <= t->lb && t->ub <= right){ return get_value(t); } T L = get_range_value(left, right, t->lch); T R = get_range_value(left, right, t->rch); return evaluate(L, R); } public: //default node value must be set // sum : 0 // max : MIN_INF // min : MAX_INF // gcd : 1 Segment_Tree_Lazy(int size_) : default_value(T()), default_lazy_value(0LL){ initialize(size_); } Segment_Tree_Lazy() : default_value(T()), default_lazy_value(0LL){ } void resize(int sz){ initialize(sz); } //node[pos] <= new_value void update(int pos, T new_value){ node* t = &v[pos + size-1]; t->value = new_value; while(t != root){ t = t->par; t->value = evaluate( get_value(t->lch), get_value(t->rch) ); } } //[l,r) += add_value void range_add(int left, int right, V z){ range_add(left, right, z, root); } //get value [left,right) T get_range_value(int left, int right){ return get_range_value(left, right, root); } void dbg(){ for(int i=0; i<v.size(); i++){ cerr << get_value(&v[i]) << " "; } cerr << endl; } }; class HL_Decomposition{ class decomposited_node{ public: Segment_Tree_Lazy<my_value, long long> seg; int size; int root; decomposited_node(){} decomposited_node(int size_, int root_) : seg(size_), size(size_), root(root_){ } }; class info{ public: decomposited_node* node; int pos; info():node(NULL){} }; int sub_tree_dfs(int pos, int par){ parent[pos] = par; int ret = 1; for(int i=0; i<G[pos].size(); i++){ int to = G[pos][i]; if(to == par) continue; ret += sub_tree_dfs(to, pos); } sub_tree_size[pos] = ret; return ret; } public: int n; vector<vector<int>> G; vector<int> parent; vector<int> sub_tree_size; vector<info> information; vector<vector<int>> decomposited_tree; vector<decomposited_node> dec_nodes; LCA lca; HL_Decomposition(vector<vector<int>>& G, int root = 0) : n(G.size()), sub_tree_size(G.size()), information(G.size()), lca(G,root), parent(G.size()){ this->G = G; sub_tree_dfs(0,0); vector<bool> visit(n, false); queue<int> head; head.push(0); while(head.size()){ int pos = head.front(); decomposited_tree.push_back({pos}); head.pop(); visit[pos] = true; while(true){ int max_size = 0; int next = -1; for(int i=0; i<G[pos].size(); i++){ int to = G[pos][i]; if(visit[to]) continue; if(max_size < sub_tree_size[to]){ if(next>=0){ head.push(next); } max_size = sub_tree_size[to]; next = to; }else{ head.push(to); } } if(next < 0) break; decomposited_tree.back().push_back(next); visit[next] = true; pos = next; } } dec_nodes.resize(decomposited_tree.size()); for(int i=0; i<decomposited_tree.size(); i++){ dec_nodes[i].size = decomposited_tree[i].size(); dec_nodes[i].root = decomposited_tree[i][0]; dec_nodes[i].seg.resize(dec_nodes[i].size); for(int j=0; j<decomposited_tree[i].size(); j++){ int pos = decomposited_tree[i][j]; information[pos].node = &dec_nodes[i]; information[pos].pos = j; dec_nodes[i].seg.update(j, my_value(c[pos], s[pos])); //cerr <<"{ " << c[pos] << ", " << s[pos] << " }, "; } //cerr << endl; } } long long query_get_val(int pos, int lca_, int type){ decomposited_node* t = information[pos].node; if(t != information[lca_].node){ long long ret = 0; int l = 0; int r = information[pos].pos+1; ret = t->seg.get_range_value(l, r).val; ret += query_get_val(parent[t->root], lca_, type); ret %= MOD; return ret; }else{ int l = information[lca_].pos; int r = information[pos].pos+1; if(type == 1) l += 1; return t->seg.get_range_value(l, r).val; } } long long query_get(int x, int y){ int lca_ = lca.get_lca(x,y); long long ret = 0; ret += query_get_val(x, lca_, 0); ret += query_get_val(y, lca_, 1); ret %= MOD; return ret; } void query_set_val(int pos, int lca_, int type, long long z){ decomposited_node* t = information[pos].node; if(t != information[lca_].node){ int l = 0; int r = information[pos].pos+1; t->seg.range_add(l, r, z); query_set_val(parent[t->root], lca_, type, z); }else{ int l = information[lca_].pos; int r = information[pos].pos+1; if(type == 1) l += 1; t->seg.range_add(l, r, z); } } void query_set(int x, int y, long long z){ int lca_ = lca.get_lca(x,y); query_set_val(x, lca_, 0, z); query_set_val(y, lca_, 1, z); } }; int main(){ int n; scanf("%d", &n); s.resize(n); c.resize(n); for(int i=0; i<n; i++){ scanf("%d", &s[i]); } for(int i=0; i<n; i++){ scanf("%d", &c[i]); } vector<vector<int>> G(n); for(int i=0; i<n-1; i++){ int a,b; scanf("%d%d", &a,&b); a--;b--; G[a].push_back(b); G[b].push_back(a); } HL_Decomposition hld(G, 0); int q; scanf("%d", &q); while(q--){ int type; scanf("%d", &type); if(type == 0){ int x,y,z; scanf("%d%d%d", &x, &y, &z); x--; y--; hld.query_set(x,y,z); }else if(type == 1){ int x,y; scanf("%d%d", &x, &y); x--; y--; long long val = hld.query_get(x,y)%MOD; printf("%lld\n", val); } } return 0; }