結果
| 問題 |
No.900 aδδitivee
|
| コンテスト | |
| ユーザー |
tonegawa
|
| 提出日時 | 2020-02-06 23:20:50 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,416 bytes |
| コンパイル時間 | 1,797 ms |
| コンパイル使用メモリ | 123,040 KB |
| 実行使用メモリ | 80,832 KB |
| 最終ジャッジ日時 | 2024-09-25 06:57:50 |
| 合計ジャッジ時間 | 14,020 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | WA * 27 |
ソースコード
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <algorithm>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <functional>
#include <iomanip>
#define vll vector<ll>
#define vvv vector<vvl>
#define vvi vector<vector<int> >
#define vvl vector<vector<ll> >
#define vv(a, b, c, d) vector<vector<d> >(a, vector<d>(b, c))
#define vvvl(a, b, c, d) vector<vvl>(a, vvl(b, vll (c, d)));
#define rep(c, a, b) for(ll c=a;c<b;c++)
#define re(c, b) for(ll c=0;c<b;c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
typedef __int128_t lll;
using namespace std;
struct segtree{
ll M=1, INIT;
vector<ll> dat;
segtree(){};
segtree(ll N, ll num){
INIT = num;
while(M<N) M*=2;
for(int i=0;i<M*2-1;i++) dat.push_back(num);
}
void update(ll x, ll k, ll l=0, int r=-1){
if(r==-1) r = M;
k+=M-1;
dat[k] += x;
while(k>0) k = (k-1)/2, dat[k] = dat[k*2+1] + dat[k*2+2];
}
ll query(ll a, ll b=-1, ll k=0, ll l=0, ll r=-1){
if(r==-1) r = M;
if(b==-1) b = M;
if(r<=a || b<=l) return INIT;
if(a<=l && r<=b) return dat[k];
ll A = query(a, b, k*2+1, l, (l+r)/2);
ll B = query(a, b, k*2+2, (l+r)/2, r);
return A + B;
}
};
struct LazySegmentTree {
private:
int n;
vector<ll> node, lazy;
segtree sg;
public:
LazySegmentTree(){};
LazySegmentTree(vector<ll> v, segtree s) {
sg = s;
int sz = (int)v.size();
n = 1; while(n < sz) n *= 2;
node.resize(2*n-1);
lazy.resize(2*n-1, 0);
for(int i=0; i<sz; i++) node[i+n-1] = v[i];
for(int i=n-2; i>=0; i--) node[i] = node[i*2+1] + node[i*2+2];
}
void eval(int k, int l, int r) {
if(lazy[k] != 0) {
node[k] += (lazy[k]*sg.dat[k]);
if(r - l > 1) {
lazy[2*k+1] += lazy[k];
lazy[2*k+2] += lazy[k];
}
lazy[k] = 0;
}
}
void add(int a, int b, ll x, int k=0, int l=0, int r=-1) {
if(r < 0) r = n;
eval(k, l, r);
if(b <= l || r <= a) return;
if(a <= l && r <= b) {
lazy[k] += x;
eval(k, l, r);
}
else {
add(a, b, x, 2*k+1, l, (l+r)/2);
add(a, b, x, 2*k+2, (l+r)/2, r);
node[k] = node[2*k+1] + node[2*k+2];
}
}
ll getsum(int a, int b, int k=0, int l=0, int r=-1) {
if(r < 0) r = n;
eval(k, l, r);
if(b <= l || r <= a) return 0;
if(a <= l && r <= b) return node[k];
ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
return vl + vr;
}
};
struct EulerTour{
ll N, root = 0, o = 0;
vector<vector<ll>> G;
LazySegmentTree seg;
segtree table;
vll begin, end, tour, depth;
vvl parent;
EulerTour(vector<vector<ll>> g){
N = g.size();
G = g;
begin.resize(N+1);
end.resize(N+1);
depth.resize(N+1);
parent.resize(30, vll(N+1));
table = segtree(2*N+1, 0);
init_();
seg = LazySegmentTree(vll(2*N+1, 0), table);
}
void init_(){
tour_init(root, -1);
lca_init();
table_init();
}
void tour_init(ll now, ll from){
begin[now] = o;
tour.push_back(now);
o++;
for(int i=0;i<G[now].size();i++){
if(G[now][i]==from) continue;
tour_init(G[now][i], now);
tour.push_back(now);
o++;
}
end[now] = o;
}
void lca_init(){
dfs(root, -1, 0);
for(int k=0;k+1<30;k++){
for(int v=0;v<N+1;v++){
if(parent[k][v]<0) parent[k+1][v] = -1;
else parent[k+1][v] = parent[k][parent[k][v]];
}
}
}
void table_init(){
for(int i=0;i<tour.size()-1;i++){
if(depth[tour[i]]>depth[tour[i+1]]) table.update(-1, i);
else table.update(1, i);
}
}
void dfs(int v, int p, int d){
parent[0][v] = p, depth[v] = d;
for(int i=0;i<G[v].size();i++) if(G[v][i] != p) dfs(G[v][i], v, d+1);
}
int lca(int u, int v){
if(depth[u]>depth[v]) swap(u, v);
for(int k=0;k<30;k++)if((depth[v]-depth[u])>>k & 1) v = parent[k][v];
if(u==v) return u;
for(int k=30-1;k>=0;k--){
if(parent[k][u] != parent[k][v]){
u = parent[k][u];
v = parent[k][v];
}
}
return parent[0][u];
}
// aの部分木の各辺にx加算
// パスa,bの値取得
void update(ll a, ll x){
seg.add(begin[a], end[a], x);
}
ll query(ll a, ll b){
ll l = lca(a, b);
ll A = seg.getsum(begin[root], begin[a]);
ll B = seg.getsum(begin[root], begin[b]);
ll C = seg.getsum(begin[root], begin[l]);
return A + B - 2*C;
}
};
struct edge{ll to, cost;};
vll d(100001, 0);
vector<vector<edge>> T(100001);
void DFS(ll now, ll from, ll c){
d[now] = c;
for(int i=0;i<T[now].size();i++){
if(T[now][i].to==from) continue;
DFS(T[now][i].to, now, c+T[now][i].cost);
}
}
int main(int argc, char const *argv[]) {
ll a, b, c, n;std::cin >> n;
vvl G = vv(n, 0, 0, ll);
re(i, n-1){
std::cin >> a >> b >> c;
G[a].push_back(b);
G[b].push_back(a);
T[a].push_back(edge{b, c});
T[b].push_back(edge{a, c});
}
DFS(0, -1, 0);
EulerTour e(G);
ll q;std::cin >> q;
re(i, q){
std::cin >> a >> b;
if(a==1) {
std::cin >> c;
e.update(b, c);
}else std::cout << e.query(0, b) + d[b] << '\n';
}
return 0;
}
tonegawa