結果
問題 | No.650 行列木クエリ |
ユーザー | butsurizuki |
提出日時 | 2024-05-07 02:47:33 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 247 ms / 2,000 ms |
コード長 | 17,935 bytes |
コンパイル時間 | 4,645 ms |
コンパイル使用メモリ | 289,732 KB |
実行使用メモリ | 71,684 KB |
最終ジャッジ日時 | 2024-11-29 15:15:13 |
合計ジャッジ時間 | 6,679 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,820 KB |
testcase_01 | AC | 101 ms
16,896 KB |
testcase_02 | AC | 247 ms
62,432 KB |
testcase_03 | AC | 2 ms
6,820 KB |
testcase_04 | AC | 108 ms
16,768 KB |
testcase_05 | AC | 247 ms
62,384 KB |
testcase_06 | AC | 2 ms
6,820 KB |
testcase_07 | AC | 2 ms
6,820 KB |
testcase_08 | AC | 109 ms
18,688 KB |
testcase_09 | AC | 236 ms
71,684 KB |
testcase_10 | AC | 2 ms
6,816 KB |
ソースコード
// HLD & verify // find "HLD starts here" #include<bits/stdc++.h> #include <algorithm> #include <cassert> #include <functional> #include <vector> #ifdef _MSC_VER #include <intrin.h> #endif #if __cplusplus >= 202002L #include <bit> #endif namespace atcoder { namespace internal { #if __cplusplus >= 202002L using std::bit_ceil; #else unsigned int bit_ceil(unsigned int n) { unsigned int x = 1; while (x < (unsigned int)(n)) x *= 2; return x; } #endif int countr_zero(unsigned int n) { #ifdef _MSC_VER unsigned long index; _BitScanForward(&index, n); return index; #else return __builtin_ctz(n); #endif } constexpr int countr_zero_constexpr(unsigned int n) { int x = 0; while (!(n & (1 << x))) x++; return x; } } // namespace internal } // namespace atcoder namespace atcoder { #if __cplusplus >= 201703L template <class S, auto op, auto e> struct segtree { static_assert(std::is_convertible_v<decltype(op), std::function<S(S, S)>>, "op must work as S(S, S)"); static_assert(std::is_convertible_v<decltype(e), std::function<S()>>, "e must work as S()"); #else template <class S, S (*op)(S, S), S (*e)()> struct segtree { #endif public: segtree() : segtree(0) {} explicit segtree(int n) : segtree(std::vector<S>(n, e())) {} explicit segtree(const std::vector<S>& v) : _n(int(v.size())) { size = (int)internal::bit_ceil((unsigned int)(_n)); log = internal::countr_zero((unsigned int)size); d = std::vector<S>(2 * size, e()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) const { assert(0 <= p && p < _n); return d[p + size]; } S prod(int l, int r) const { assert(0 <= l && l <= r && r <= _n); S sml = e(), smr = e(); l += size; r += size; while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() const { return d[1]; } template <bool (*f)(S)> int max_right(int l) const { return max_right(l, [](S x) { return f(x); }); } template <class F> int max_right(int l, F f) const { assert(0 <= l && l <= _n); assert(f(e())); if (l == _n) return _n; l += size; S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!f(op(sm, d[l]))) { while (l < size) { l = (2 * l); if (f(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template <bool (*f)(S)> int min_left(int r) const { return min_left(r, [](S x) { return f(x); }); } template <class F> int min_left(int r, F f) const { assert(0 <= r && r <= _n); assert(f(e())); if (r == 0) return 0; r += size; S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!f(op(d[r], sm))) { while (r < size) { r = (2 * r + 1); if (f(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector<S> d; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } }; } // namespace atcoder #include <algorithm> #include <cassert> #include <functional> #include <vector> namespace atcoder { #if __cplusplus >= 201703L template <class S, auto op, auto e, class F, auto mapping, auto composition, auto id> struct lazy_segtree { static_assert(std::is_convertible_v<decltype(op), std::function<S(S, S)>>, "op must work as S(S, S)"); static_assert(std::is_convertible_v<decltype(e), std::function<S()>>, "e must work as S()"); static_assert( std::is_convertible_v<decltype(mapping), std::function<S(F, S)>>, "mapping must work as F(F, S)"); static_assert( std::is_convertible_v<decltype(composition), std::function<F(F, F)>>, "compostiion must work as F(F, F)"); static_assert(std::is_convertible_v<decltype(id), std::function<F()>>, "id must work as F()"); #else template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()> struct lazy_segtree { #endif public: lazy_segtree() : lazy_segtree(0) {} explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {} explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) { size = (int)internal::bit_ceil((unsigned int)(_n)); log = internal::countr_zero((unsigned int)size); d = std::vector<S>(2 * size, e()); lz = std::vector<F>(size, id()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); return d[p]; } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); if (l == r) return e(); l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } S sml = e(), smr = e(); while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } void apply(int p, F f) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = mapping(f, d[p]); for (int i = 1; i <= log; i++) update(p >> i); } void apply(int l, int r, F f) { assert(0 <= l && l <= r && r <= _n); if (l == r) return; l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } { int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l >>= 1; r >>= 1; } l = l2; r = r2; } for (int i = 1; i <= log; i++) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } template <bool (*g)(S)> int max_right(int l) { return max_right(l, [](S x) { return g(x); }); } template <class G> int max_right(int l, G g) { assert(0 <= l && l <= _n); assert(g(e())); if (l == _n) return _n; l += size; for (int i = log; i >= 1; i--) push(l >> i); S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!g(op(sm, d[l]))) { while (l < size) { push(l); l = (2 * l); if (g(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template <bool (*g)(S)> int min_left(int r) { return min_left(r, [](S x) { return g(x); }); } template <class G> int min_left(int r, G g) { assert(0 <= r && r <= _n); assert(g(e())); if (r == 0) return 0; r += size; for (int i = log; i >= 1; i--) push((r - 1) >> i); S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!g(op(d[r], sm))) { while (r < size) { push(r); r = (2 * r + 1); if (g(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector<S> d; std::vector<F> lz; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } void all_apply(int k, F f) { d[k] = mapping(f, d[k]); if (k < size) lz[k] = composition(f, lz[k]); } void push(int k) { all_apply(2 * k, lz[k]); all_apply(2 * k + 1, lz[k]); lz[k] = id(); } }; } // namespace atcoder using namespace std; using namespace atcoder; // HLD starts here using Graph=vector<vector<int>>; using pi=pair<int,int>; struct HLD{ vector<int> pareg; vector<int> backeg; vector<int> dep; int cureg; vector<int> topv; vector<int> tope; bool vwei; // true: vertex-weighted, false: edge-weighted HLD(int n,Graph &g,bool vw,int root=0){ vwei=vw; dfs1(root,-1,g); pareg.resize(n); backeg.resize(n); dep.resize(n); topv.resize(n); tope.resize(n); cureg=1; pareg[root]=0; topv[0]=-1; tope[0]=0; dfs2(root,-1,0,true,g); } int dfs1(int v,int pv,Graph &g){ int res=1; int uid=-1,umax=-1; for(int i=0;i<g[v].size();i++){ if(g[v][i]==pv){continue;} int und=dfs1(g[v][i],v,g); res+=und; if(umax<und){ umax=und; uid=i; } } if(uid>0){ swap(g[v][uid],g[v][0]); } return res; } void dfs2(int v,int pv,int cdep,bool upheav,Graph &g){ dep[v]=cdep; for(int i=0;i<g[v].size();i++){ if(g[v][i]==pv){continue;} if(i==0){ // heavy if(upheav){ topv[cureg]=topv[pareg[v]]; tope[cureg]=tope[pareg[v]]; } else{ topv[cureg]=v; tope[cureg]=cureg; } pareg[g[v][i]]=cureg; cureg++; dfs2(g[v][i],v,cdep+1,true,g); } else{ // light topv[cureg]=v; tope[cureg]=cureg; pareg[g[v][i]]=cureg; cureg++; dfs2(g[v][i],v,cdep+1,false,g); } } backeg[v]=cureg; } // single vertex (for vertex-weighted) int single(int v){ return pareg[v]; } // subtree is [l,r] pi subtree(int v){ if(vwei){ return {pareg[v],backeg[v]-1}; } else{ return {pareg[v]+1,backeg[v]-1}; } } // u->v path is {[l0,r0], [l1,r1], ...} // each segments may reversed (so li<=ri may NOT be satisfied) vector<pi> path(int u,int v){ vector<pi> uu; vector<pi> vv; while(u!=v){ if(tope[pareg[u]]==tope[pareg[v]]){ // same path if(dep[u]>dep[v]){ // u goes up uu.push_back({pareg[u],pareg[u]-(dep[u]-dep[v]-1)}); u=v; } else{ // v goes up vv.push_back({pareg[v],pareg[v]-(dep[v]-dep[u]-1)}); v=u; } break; } int du=-1; int dv=-1; if(topv[pareg[u]]>=0){du=dep[topv[pareg[u]]];} if(topv[pareg[v]]>=0){dv=dep[topv[pareg[v]]];} if(du>dv){ // u goes up uu.push_back({pareg[u],tope[pareg[u]]}); u=topv[pareg[u]]; } else{ // v goes up vv.push_back({pareg[v],tope[pareg[v]]}); v=topv[pareg[v]]; } } vector<pi> res; for(auto &nx : uu){ res.push_back(nx); } if(vwei){ res.push_back({pareg[u],pareg[u]}); } reverse(vv.begin(),vv.end()); for(auto &nx : vv){ swap(nx.first,nx.second); res.push_back(nx); } return res; } }; long long op_sum(long long a,long long b){ return (a+b); } long long e_sum(){ return 0; } // https://judge.yosupo.jp/problem/vertex_add_path_sum void val_yosupo_VAPS(){ int n,q; cin >> n >> q; vector<int> a(n); for(auto &nx : a){cin >> nx;} Graph g(n); for(int i=0;i<n-1;i++){ int u,v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } HLD hld(n,g,true); // vertex-weighted vector<long long> ini(n,0); for(int i=0;i<n;i++){ ini[hld.single(i)]=a[i]; } segtree<long long,op_sum,e_sum> seg(ini); while(q>0){ q--; int typ; cin >> typ; if(typ==0){ int u; long long x; cin >> u >> x; int pos=hld.single(u); seg.set(pos,seg.get(pos)+x); } else{ int u,v; cin >> u >> v; vector<pi> ss=hld.path(u,v); long long res=0; for(auto &nx : ss){ res+=seg.prod(min(nx.first,nx.second),max(nx.first,nx.second)+1); } cout << res << "\n"; } } } #define mod 998244353 using pl=pair<long long,long long>; pl op_aff(pl l,pl r){ return { (l.first*r.first)%mod, (l.second*r.first+r.second)%mod }; } pl e_aff(){return {1,0};} // https://judge.yosupo.jp/problem/vertex_set_path_composite void val_yosupo_VSPC(){ int n,q; cin >> n >> q; vector<pl> a(n); for(auto &nx : a){ cin >> nx.first >> nx.second; } Graph g(n); for(int i=0;i<n-1;i++){ int u,v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } HLD hld(n,g,true); // vertex-weighted vector<pl> ini(2*n); for(int i=0;i<n;i++){ ini[hld.single(i)]=a[i]; ini[2*n-1-hld.single(i)]=a[i]; } segtree<pl,op_aff,e_aff> seg(ini); while(q>0){ q--; int typ; cin >> typ; if(typ==0){ int p; pl x; cin >> p >> x.first >> x.second; seg.set(hld.single(p),x); seg.set(2*n-1-hld.single(p),x); } else{ int u,v; long long x; cin >> u >> v >> x; vector<pi> ss=hld.path(u,v); pl cf=e_aff(); for(auto &nx : ss){ if(nx.first<=nx.second){ cf=op_aff(cf,seg.prod(nx.first,nx.second+1)); } else{ cf=op_aff(cf,seg.prod((2*n-1-nx.first),(2*n-1-nx.second)+1)); } } cout << (x*cf.first+cf.second)%mod << "\n"; } } } #define mod107 1000000007 using vl=vector<long long>; vl op_mat2(vl l,vl r){ return { (l[0]*r[0]+l[1]*r[2])%mod107, (l[0]*r[1]+l[1]*r[3])%mod107, (l[2]*r[0]+l[3]*r[2])%mod107, (l[2]*r[1]+l[3]*r[3])%mod107 }; } vl e_mat2(){ return {1,0,0,1}; } // https://yukicoder.me/problems/no/650 void val_ykc_650(){ int n; cin >> n; Graph g(n); vector<int> uu(n-1),vv(n-1); for(int i=0;i<n-1;i++){ int u,v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); uu[i]=u; vv[i]=v; } HLD hld(n,g,false); segtree<vl,op_mat2,e_mat2> seg(2*n); int q; cin >> q; while(q>0){ q--; string typ; cin >> typ; if(typ[0]=='x'){ int i; cin >> i; if(hld.dep[uu[i]]<hld.dep[vv[i]]){ swap(uu[i],vv[i]); } int eid=hld.pareg[uu[i]]; vl x=e_mat2(); for(auto &nx : x){cin >> nx;} seg.set(eid,x); seg.set(2*n-1-eid,x); } else{ int u,v; cin >> u >> v; vector<pi> pt=hld.path(u,v); vl x=e_mat2(); for(auto &nx : pt){ if(nx.first<=nx.second){ x=op_mat2(x,seg.prod(nx.first,nx.second+1)); } else{ x=op_mat2(x,seg.prod(2*n-1-nx.first,(2*n-1-nx.second)+1)); } } cout << x[0] << " "; cout << x[1] << " "; cout << x[2] << " "; cout << x[3] << "\n"; } } } // https://betrue12.hateblo.jp/entry/2020/09/23/005940#%E5%8C%BA%E9%96%93%E5%8A%A0%E7%AE%97%E5%8C%BA%E9%96%93%E5%92%8C%E5%8F%96%E5%BE%97 struct S{ long long value; int size; }; using F = long long; S op_S(S a, S b){ return {a.value+b.value, a.size+b.size}; } S e_S(){ return {0, 0}; } S mapping(F f, S x){ return {x.value + f*x.size, x.size}; } F composition(F f, F g){ return f+g; } F id(){ return 0; } // https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2667 void val_AOJ_2667(){ int n,q; cin >> n >> q; Graph g(n); for(int i=0;i<(n-1);i++){ int u,v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } std::vector<S> v(n, {0, 1}); atcoder::lazy_segtree<S, op_S, e_S, F, mapping, composition, id> seg(v); HLD hld(n,g,false); while(q>0){ q--; int typ; cin >> typ; if(typ==0){ long long res=0; int u,v; cin >> u >> v; vector<pi> pt=hld.path(u,v); for(auto &nx : pt){ res+=seg.prod(min(nx.first,nx.second),max(nx.first,nx.second)+1).value; } cout << res << "\n"; } else{ int v; long long x; cin >> v >> x; pi st=hld.subtree(v); seg.apply(st.first,st.second+1,x); } } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); // val_yosupo_VAPS(); // val_yosupo_VSPC(); val_ykc_650(); // val_AOJ_2667(); return 0; }