#include using namespace std; using Int = long long; template inline void chmin(T1 &a,T2 b){if(a>b) a=b;} template inline void chmax(T1 &a,T2 b){if(a struct SquareMatrix{ typedef array arr; typedef array mat; mat dat; SquareMatrix(){ for(size_t i=0;i>=1; } return res; } }; //END CUT HERE template struct Mint{ T v; Mint():v(0){} Mint(signed v):v(v){} Mint(long long t){v=t%MOD;if(v<0) v+=MOD;} Mint pow(long long k){ Mint res(1),tmp(v); while(k){ if(k&1) res*=tmp; tmp*=tmp; k>>=1; } return res; } Mint inv(){return pow(MOD-2);} Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;} Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;} Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;} Mint& operator/=(Mint a){return (*this)*=a.inv();} Mint operator+(Mint a) const{return Mint(v)+=a;}; Mint operator-(Mint a) const{return Mint(v)-=a;}; Mint operator*(Mint a) const{return Mint(v)*=a;}; Mint operator/(Mint a) const{return Mint(v)/=a;}; Mint operator-(){return v?MOD-v:v;} bool operator==(const Mint a)const{return v==a.v;} bool operator!=(const Mint a)const{return v!=a.v;} bool operator <(const Mint a)const{return v vector compress(vector v){ sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); return v; } template map dict(const vector &v){ map res; for(Int i=0;i<(Int)v.size();i++) res[v[i]]=i; return res; } template struct SegmentTree{ Int n; F f; T ti; vector dat; SegmentTree(){}; SegmentTree(F f,T ti):f(f),ti(ti){} void init(Int n_){ n=1; while(n &v){ Int n_=v.size(); init(n_); for(Int i=0;i>=1) dat[k]=f(dat[(k<<1)|0],dat[(k<<1)|1]); } T query(Int a,Int b){ T vl=ti,vr=ti; for(Int l=a+n,r=b+n;l>=1,r>>=1) { if(l&1) vl=f(vl,dat[l++]); if(r&1) vr=f(dat[--r],vr); } return f(vl,vr); } }; //INSERT ABOVE HERE signed YAHOO2019_FINAL_D(){ using M = Mint; using MM = SquareMatrix; Int n,q; cin>>n>>q; vector ts(q),ls(q),rs(q),ps(q); for(Int i=0;i>ts[i]; if(ts[i]==1) cin>>ps[i]; if(ts[i]==2) cin>>ls[i]>>rs[i]; } vector vs; for(Int i=0;i vt(vs.size()-1,A); for(Int i=0;i+1<(Int)vs.size();i++){ vt[i]=A.pow(vs[i+1]-vs[i]); } MM I=MM::identity(); auto f=[&](MM a,MM b){return MM::cross(b,a);}; SegmentTree seg(f,I); seg.build(vt); vector used(vs.size(),0); for(Int i=0;i>s; using M = SquareMatrix; auto f=[](M a,M b){return M::cross(a,b);}; M ti=M::identity(); SegmentTree seg(f,ti); vector vt(s.size(),ti); for(int i=0;i<(int)s.size();i++){ if(s[i]=='D') vt[i][0][1]=1; if(s[i]=='I') vt[i][1][2]=1; if(s[i]=='S') vt[i][2][3]=1; if(s[i]=='C') vt[i][3][4]=1; if(s[i]=='O') vt[i][4][5]=1; } seg.build(vt); int q; cin>>q; for(int i=0;i>l>>r; l--; cout< > G; vector vid, head, sub, par, dep, inv, type; HLDecomposition(){} HLDecomposition(int n): n(n),pos(0),G(n),vid(n,-1),head(n),sub(n,1), par(n,-1),dep(n,0),inv(n),type(n){} void add_edge(int u, int v) { G[u].push_back(v); G[v].push_back(u); } void build(vector rs={0}) { int c=0; for(int r:rs){ dfs_sz(r); head[r]=r; dfs_hld(r,c++); } } void dfs_sz(int v) { for(int &u:G[v]){ if(u==par[v]) continue; par[u]=v; dep[u]=dep[v]+1; dfs_sz(u); sub[v]+=sub[u]; if(sub[u]>sub[G[v][0]]) swap(u,G[v][0]); } } void dfs_hld(int v,int c) { vid[v]=pos++; inv[vid[v]]=v; type[v]=c; for(int u:G[v]){ if(u==par[v]) continue; head[u]=(u==G[v][0]?head[v]:u); dfs_hld(u,c); } } // for_each(edge) // [l,r] <- attention!! template void for_each_edge(int u, int v,const F& f) { while(1){ if(vid[u]>vid[v]) swap(u,v); if(head[u]!=head[v]){ f(vid[head[v]],vid[v]); v=par[head[v]]; }else{ if(u!=v) f(vid[u]+1,vid[v]); break; } } } int lca(int u,int v){ while(1){ if(vid[u]>vid[v]) swap(u,v); if(head[u]==head[v]) return u; v=par[head[v]]; } } }; signed YUKI_650(){ using M = Mint; using MM = SquareMatrix; auto f=[](MM a,MM b){return MM::cross(a,b);}; int n; cin>>n; HLDecomposition hld(n); vector X,Y; for(int i=1;i>a>>b; X.emplace_back(a); Y.emplace_back(b); hld.add_edge(a,b); } hld.build(); MM ti=MM::identity(); SegmentTree seg(f,ti); seg.build(vector(n,ti)); int q; cin>>q; for(int i=0;i>c; if(c=='x'){ int v,a,b,c,d; cin>>v>>a>>b>>c>>d; int x=max(hld.vid[X[v]],hld.vid[Y[v]]); MM tmp; tmp[0][0]=M(a);tmp[0][1]=M(b); tmp[1][0]=M(c);tmp[1][1]=M(d); seg.set_val(x,tmp); } if(c=='g'){ int x,y; cin>>x>>y; MM ans; auto q=[&](int l,int r){ans=f(seg.query(l,r+1),ans);}; hld.for_each_edge(x,y,q); cout<