#include #include #include #include #include #ifdef _MSC_VER #include #endif #if __cplusplus >= 202002L #include #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 struct segtree { static_assert(std::is_convertible_v>, "op must work as S(S, S)"); static_assert(std::is_convertible_v>, "e must work as S()"); #else template struct segtree { #endif public: segtree() : segtree(0) {} explicit segtree(int n) : segtree(std::vector(n, e())) {} explicit segtree(const std::vector& v) : _n(int(v.size())) { size = (int)internal::bit_ceil((unsigned int)(_n)); log = internal::countr_zero((unsigned int)size); d = std::vector(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 int max_right(int l) const { return max_right(l, [](S x) { return f(x); }); } template 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 int min_left(int r) const { return min_left(r, [](S x) { return f(x); }); } template 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 d; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } }; } // namespace atcoder #include #include #include #include namespace atcoder { #if __cplusplus >= 201703L template struct lazy_segtree { static_assert(std::is_convertible_v>, "op must work as S(S, S)"); static_assert(std::is_convertible_v>, "e must work as S()"); static_assert( std::is_convertible_v>, "mapping must work as F(F, S)"); static_assert( std::is_convertible_v>, "compostiion must work as F(F, F)"); static_assert(std::is_convertible_v>, "id must work as F()"); #else template struct lazy_segtree { #endif public: lazy_segtree() : lazy_segtree(0) {} explicit lazy_segtree(int n) : lazy_segtree(std::vector(n, e())) {} explicit lazy_segtree(const std::vector& v) : _n(int(v.size())) { size = (int)internal::bit_ceil((unsigned int)(_n)); log = internal::countr_zero((unsigned int)size); d = std::vector(2 * size, e()); lz = std::vector(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 int max_right(int l) { return max_right(l, [](S x) { return g(x); }); } template 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 int min_left(int r) { return min_left(r, [](S x) { return g(x); }); } template 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 d; std::vector 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; using Graph=vector>; using pi=pair; struct HLD{ vector pareg; vector backeg; vector dep; int cureg; vector topv; vector 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;i0){ 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;iv path is {[l0,r0], [l1,r1], ...} // each segments may reversed (so li<=ri may NOT be satisfied) vector path(int u,int v){ vector uu; vector 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 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 a(n); for(auto &nx : a){cin >> nx;} Graph g(n); for(int i=0;i> u >> v; g[u].push_back(v); g[v].push_back(u); } HLD hld(n,g,true); // vertex-weighted vector ini(n,0); for(int i=0;i 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 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; 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 a(n); for(auto &nx : a){ cin >> nx.first >> nx.second; } Graph g(n); for(int i=0;i> u >> v; g[u].push_back(v); g[v].push_back(u); } HLD hld(n,g,true); // vertex-weighted vector ini(2*n); for(int i=0;i 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 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; 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}; } void val_ykc_650(){ int n; cin >> n; Graph g(n); vector uu(n-1),vv(n-1); for(int i=0;i> u >> v; g[u].push_back(v); g[v].push_back(u); uu[i]=u; vv[i]=v; } HLD hld(n,g,false); segtree 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]]> nx;} seg.set(eid,x); seg.set(2*n-1-eid,x); } else{ int u,v; cin >> u >> v; vector 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"; } } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); // val_yosupo_VAPS(); // val_yosupo_VSPC(); val_ykc_650(); return 0; }