結果

問題 No.900 aδδitivee
ユーザー NyaanNyaanNyaanNyaan
提出日時 2019-10-04 21:57:29
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 183 ms / 2,000 ms
コード長 10,363 bytes
コンパイル時間 2,492 ms
コンパイル使用メモリ 185,968 KB
実行使用メモリ 28,852 KB
最終ジャッジ日時 2024-04-14 10:39:32
合計ジャッジ時間 7,853 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 2 ms
6,944 KB
testcase_04 AC 2 ms
6,940 KB
testcase_05 AC 2 ms
6,940 KB
testcase_06 AC 2 ms
6,944 KB
testcase_07 AC 162 ms
23,152 KB
testcase_08 AC 164 ms
23,156 KB
testcase_09 AC 158 ms
23,080 KB
testcase_10 AC 161 ms
23,148 KB
testcase_11 AC 155 ms
23,180 KB
testcase_12 AC 163 ms
23,056 KB
testcase_13 AC 163 ms
23,056 KB
testcase_14 AC 164 ms
23,048 KB
testcase_15 AC 163 ms
23,108 KB
testcase_16 AC 161 ms
23,176 KB
testcase_17 AC 164 ms
23,120 KB
testcase_18 AC 167 ms
23,212 KB
testcase_19 AC 183 ms
23,104 KB
testcase_20 AC 164 ms
23,196 KB
testcase_21 AC 162 ms
23,160 KB
testcase_22 AC 140 ms
28,784 KB
testcase_23 AC 133 ms
28,640 KB
testcase_24 AC 139 ms
28,852 KB
testcase_25 AC 141 ms
28,780 KB
testcase_26 AC 136 ms
28,696 KB
testcase_27 AC 138 ms
28,636 KB
testcase_28 AC 140 ms
28,712 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#define whlie while
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define rep(i,N) for(int i = 0; i < (N); i++)
#define repr(i,N) for(int i = (N) - 1; i >= 0; i--)
#define rep1(i,N) for(int i = 1; i <= (N) ; i++)
#define repr1(i,N) for(int i = (N) ; i > 0 ; i--)
#define each(x,v) for(auto& x : v)
#define all(v) (v).begin(),(v).end()
#define sz(v) ((int)(v).size())
#define vrep(v,it) for(auto it = v.begin(); it != v.end(); it++)
#define vrepr(v,it) for(auto it = v.rbegin(); it != v.rend(); it++)
#define ini(...) int __VA_ARGS__; in(__VA_ARGS__)
#define inl(...) ll __VA_ARGS__; in(__VA_ARGS__)
#define ins(...) string __VA_ARGS__; in(__VA_ARGS__)
using namespace std; void solve();
using ll = long long; using vl = vector<ll>;
using vi = vector<int>; using vvi = vector< vector<int> >;
constexpr int inf = 1001001001;
constexpr ll infLL = (1LL << 61) - 1;
struct IoSetupNya {IoSetupNya() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(7);} } iosetupnya;
template<typename T, typename U> inline bool amin(T &x, U y) { return (y < x) ? (x = y, true) : false; }
template<typename T, typename U> inline bool amax(T &x, U y) { return (x < y) ? (x = y, true) : false; }
template<typename T, typename U> ostream& operator <<(ostream& os, const pair<T, U> &p) { os << p.first << " " << p.second; return os; }
template<typename T, typename U> istream& operator >>(istream& is, pair<T, U> &p) { is >> p.first >> p.second; return is; }
template<typename T> ostream& operator <<(ostream& os, const vector<T> &v) { int s = (int)v.size(); rep(i,s) os << (i ? " " : "") << v[i]; return os; }
template<typename T> istream& operator >>(istream& is, vector<T> &v) { for(auto &x : v) is >> x; return is; }
void in(){} template <typename T,class... U> void in(T &t,U &...u){ cin >> t; in(u...);}
void out(){cout << "\n";} template <typename T,class... U> void out(const T &t,const U &...u){ cout << t; if(sizeof...(u)) cout << " "; out(u...);}
template<typename T>void die(T x){out(x); exit(0);}
#ifdef NyaanDebug
  #include "NyaanDebug.h"
  #define trc(...) do { cerr << #__VA_ARGS__ << " = "; dbg_out(__VA_ARGS__);} while(0)
  #define trca(v,N) do { cerr << #v << " = "; array_out(v , N);cout << endl;} while(0)
#else
  #define trc(...)
  #define trca(...)
  int main(){solve();}
#endif

using P = pair<int,int>; using vp = vector<P>;
constexpr int MOD = /** 1000000007; //*/ 998244353;
///////////////////////////////////////////////////////////

template< typename T >
struct edge {
  int src, to;
  T cost;

  edge(int to) : src(-1) , to(to) , cost(0){}
  edge(int to, T cost) : src(-1), to(to), cost(cost) {}
  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) { // edge e = n; とできる(e.to = n)
    to = x;
    return *this;
  }

  // int()をオーバーロードすることで重み付きグラフと普通のグラフでライブラリを共用できる
  operator int() const { return to; } // v[e]とできる ( v[e.to]に同じ )

};

// sort用 とりあえずcostの小さいほうが左としているが適宜書き換えて使いましょう
/**
template<typename T>
bool operator <(const edge<T>& e1,const edge<T>& e2){ 
  return e1.cost < e2.cost;
}//*/
template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WG = vector< Edges< T > >;
template< typename T>
using UWG = vector< vector <int> >;

// HL分解
// 木の内部の任意の2点間をO(log_V)個に分割するデータ構造。
// これを用いることで木に対してセグ木やbitなどのデータ構造を用いることが出来る。
// 以下、内部のデータの説明。(頂点0を根とした。)
// size[i] ... iの部分木の要素数 depth[i] ... iの深さ(depth[0] = 0)
// nxt[i] ... vから根に向かって伸びるheavy pathの終着点(nxt[0] = 0)
// in[i],out[i] ... オイラーツアーした時の順番。
// [ in[i] , out[i] )で部分木へのクエリとなる。
// [ in[nxt[i]] , in[v] ]でheavy pathへのクエリとなる。
// par[i] ... iの親ノード。 (par[0] = 0)
// verify
// ABC133F https://atcoder.jp/contests/abc133/submissions/6357522
// AOJ-GRL-5C http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=3742268#1
// AOJ-GRL-5D https://onlinejudge.u-aizu.ac.jp/status/users/NyaanNyaan/submissions/1/GRL_5_D/judge/3742298/C++14
// AOJ-GRL-5E https://onlinejudge.u-aizu.ac.jp/status/users/NyaanNyaan/submissions/1/GRL_5_E/judge/3742347/C++14

WG<ll> g;

struct HLD{
  int idx;
  vector<int> size, depth, in, out, nxt, par;
  HLD(int N,int root = 0):idx(0),size(N,0),depth(N,0),in(N,-1),
    out(N,-1),nxt(N,0),par(N,0){
    dfs_sz(root);
    trc(size); trc(depth);
    dfs_hld(root);
    trc(in); trc(out); trc(nxt);trc(par);
  }
  
  void build(int root){
    dfs_sz(root);
    dfs_hld(root);
  }

  // 構築
  void dfs_sz(int cur){
    size[cur] = 1;
    for(auto &dst: g[cur]){
      if(dst == par[cur]) {
        if( g[cur].size() >= 2 && int(dst) == int(g[cur][0]) ) 
          swap(g[cur][0] , g[cur][1]);
        else continue;
      }
      depth[dst] = depth[cur] + 1;
      par[dst] = cur;
      dfs_sz(dst);
      size[cur] += size[dst];
      if(size[dst] > size[g[cur][0]]){
        swap(dst , g[cur][0]);
      }
    }
  }
  void dfs_hld(int cur){
    in[cur] = idx++;
    for(auto dst: g[cur]){
      if(dst == par[cur]) continue;
      nxt[dst] = ( int(dst) == int(g[cur][0]) ? nxt[cur] : int(dst) );
      dfs_hld(dst);
    }
    out[cur] = idx;
  }

  // 辺クエリ
  // aからbへの辺(aが根の側,bが葉の側)の持つ値をstのdata[b]に代入しているとする。
  // (すなわち、辺のデータを葉の方の頂点に移し替える。)
  // (注: 例外処理のためdata[0] = fの単位元とする。)
  // この時、st.query(u,v + 1)はpar[u]からvまでの辺へのクエリとなる。
  // (注: st.query()は引数に半開区間をため第二引数のvに1を足している。)
  // これをもとに[u , v]の辺へのクエリを実装する。

  template<typename F>
  void edge_query(int u,int v,const F& f){
    while(1){
      if(in[u] > in[v]) swap(u,v);
      trc(u,v);
      if(nxt[u] != nxt[v]){
        f(in[nxt[v]] , in[v] + 1);
        v = par[ nxt[v] ];
      }
      else{
        trc(u , v,in[u] , in[v]);
        if(u != v) f(in[u] + 1, in[v] + 1);
        break;
      }
    }
  }

  // 頂点クエリ (verifyしていない)
  // 辺クエリと同様の議論をする。
  // たぶん最後の同じheavy pathに載ったところを、
  // in[u]+1からin[u]にかえれば正しく動くと思う。
  template<typename F>
  void node_query(int u,int v,const F& f){
    while(1){
      if(in[u] > in[v]) swap(u,v);
      trc(u,v);
      if(nxt[u] != nxt[v]){
        f(in[nxt[v]] , in[v] + 1);
        v = par[ nxt[v] ];
      }
      else{
        trc(u , v,in[u] , in[v]);
        f(in[u], in[v] + 1);
        break;
      }
    }
  }

  // 部分木クエリ
  template<typename F>
  void sub_edge_query(int u,const F& f){
    f(in[u] + 1, out[u]);
  }
  template<typename F>
  void sub_node_query(int u,const F& f){
    f(in[u], out[u]);
  }

  // 最小共通祖先 
  int lca(int a,int b){
    while(nxt[a] != nxt[b]){
      if( in[a] < in[b] ) swap(a,b);
      a = par[nxt[a]];
    }
    return depth[a] < depth[b] ? a : b;
  }
};

vl memo;
void dfs(int cur , int par , ll cost){
  if(cur == 0) memo[cur] = 0;
  else memo[cur] = memo[par] + cost;
  each(x , g[cur]){
    if(x == par) continue;
    dfs(x , cur , x.cost);
  }
}

// 遅延伝播セグメント木
template <typename T,typename E,typename F,typename G,typename H>
struct LST{
  int n,height;
  F f;
  G g;
  H h;
  T ti;
  E ei;
  vector<T> dat;
  vector<E> laz;
  LST(int n, F f,G g,H h,T ti,E ei):
    f(f),g(g),h(h),ti(ti),ei(ei){
      init(n);
  }
  LST(const vector<T> &v, F f,G g,H h,T ti,E ei):
    f(f),g(g),h(h),ti(ti),ei(ei){
      init( (int)v.size() );
      build(v);
  }
  
  void init(int n_){
    n=1;height=0;
    while(n<n_) n<<=1,height++;
    dat.assign(2*n,ti);
    laz.assign(2*n,ei);
  }
  void build(const vector<T> &v){
    int n_=v.size();
    init(n_);
    for(int i=0;i<n_;i++) dat[n+i]=v[i];
    for(int i=n-1;i;i--)
      dat[i]=f(dat[(i<<1)|0],dat[(i<<1)|1]);
  }
  inline T reflect(int k){
    return laz[k]==ei?dat[k]:g(dat[k],laz[k]);
  }
  inline void eval(int k){
    if(laz[k]==ei) return;
    laz[(k<<1)|0]=h(laz[(k<<1)|0],laz[k]);
    laz[(k<<1)|1]=h(laz[(k<<1)|1],laz[k]);
    dat[k]=reflect(k);
    laz[k]=ei;
  }
  inline void thrust(int k){
    for(int i=height;i;i--) eval(k>>i);
  }
  inline void recalc(int k){    
    while(k>>=1)
      dat[k]=f(reflect((k<<1)|0),reflect((k<<1)|1));
  }
  void update(int a,int b,E x){
    thrust(a+=n);
    thrust(b+=n-1);
    for(int l=a,r=b+1;l<r;l>>=1,r>>=1){
      if(l&1) laz[l]=h(laz[l],x),l++;
      if(r&1) --r,laz[r]=h(laz[r],x);
    }
    recalc(a);
    recalc(b);
  }
  void set_val(int a,T x){
    thrust(a+=n);
    dat[a]=x;laz[a]=ei;
    recalc(a);
  }
  T query(int a,int b){
    thrust(a+=n);
    thrust(b+=n-1);
    T vl=ti,vr=ti;
    for(int l=a,r=b+1;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,reflect(l++));
      if(r&1) vr=f(reflect(--r),vr);
    }
    return f(vl,vr);
  }
};

void solve(){
  ini(N);
  memo.resize(N , 0);
  g.resize(N);
  Edges<ll> es;
  rep(_,N-1){
    inl(a,b,c);
    g[a].eb(b,c); g[b].eb(a,c);
    es.eb(a , b , c);

  }
  HLD hld(N);

  // 区間にaを足す・区間和を取得
  using P = pair<ll,ll>;
  auto f = [](P a,P b){
    return P( a.fi+b.fi, a.se+b.se );
  };
  auto gg = [](P a,ll b){
    return P( a.fi+b*a.se, a.se);
  };
  auto h = [](ll a,ll b){
    return a+b;
  };
  vector<P> v(N, P(0,1));

  each(e,es){
    trc(e.to);
    trc(hld.in[e.to]);
    v[hld.in[e.to]].fi = e.cost;
  }

  LST<P,ll,decltype(f),decltype(gg),decltype(h)>
    lst (v,f,gg,h,P(0,0),0);
  
  ini(Q);
  rep(i,Q){
    ini(cmd);
    if(cmd == 1){
      inl(a , x);
      hld.sub_edge_query(a , [&](int aa,int bb){
        lst.update(aa , bb , x);
      });
    }
    else {
      ini(b);
      trc(cmd , b);
      ll ans = 0;
      hld.edge_query(0 , b , [&](int aa,int bb){
        ans += lst.query(aa , bb).fi;
      });
      out(ans);
    }
  }

  

  


}
0