結果
問題 | No.650 行列木クエリ |
ユーザー | Taiki0715 |
提出日時 | 2023-08-27 12:36:10 |
言語 | C++17(clang) (17.0.6 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,066 ms / 2,000 ms |
コード長 | 8,060 bytes |
コンパイル時間 | 7,115 ms |
コンパイル使用メモリ | 186,728 KB |
実行使用メモリ | 218,908 KB |
最終ジャッジ日時 | 2024-06-08 08:11:40 |
合計ジャッジ時間 | 13,721 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 449 ms
51,120 KB |
testcase_02 | AC | 1,058 ms
203,400 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 461 ms
51,124 KB |
testcase_05 | AC | 1,066 ms
203,512 KB |
testcase_06 | AC | 1 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 512 ms
54,224 KB |
testcase_09 | AC | 1,061 ms
218,908 KB |
testcase_10 | AC | 1 ms
5,376 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; #if __has_include(<atcoder/all>) #include <atcoder/all> using namespace atcoder; template<int mod>istream &operator>>(istream &is,static_modint<mod> &a){long long b;is>>b;a=b;return is;} istream &operator>>(istream &is,modint &a){long long b;cin>>b;a=b;return is;} #endif using ll=long long; using ull=unsigned long long; using P=pair<ll,ll>; template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>; template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);} template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);} template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;} template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;} template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;} template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;} template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;} template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;} #define reps(i,a,n) for(int i=(a);i<(n);i++) #define rep(i,n) reps(i,0,n) #define all(x) x.begin(),x.end() #define pcnt(x) __builtin_popcount(x) ll myceil(ll a,ll b){return (a+b-1)/b;} template<typename T> vector<T> vec(T d,int sz){ return vector<T>(sz,d); } template<typename T,typename... U> auto vec(T d,int a,U...b){ return vector<decltype(vec<T>(d,b...))>(a,vec<T>(d,b...)); } #ifdef LOCAL #include "debug.h" #else #define debug(...) static_cast<void>(0) template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;} #endif void SOLVE(); int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); #ifdef LOCAL clock_t start=clock(); #endif int testcase=1; //cin>>testcase; for(int i=0;i<testcase;i++){ SOLVE(); } #ifdef LOCAL cout<<"time:"; cout<<(clock()-start)/1000; cout<<"ms\n"; #endif } struct HeavyLightDecomposition{ private: int n; vector<vector<int>>to; int root; vector<int>par,pathtop,in,out; public: vector<int>stsize; private: void st_dfs(int x,int p){ par[x]=p; stsize[x]=1; for(auto &i:to[x]){ if(i==p){ if(i==to[x].back())break; else swap(i,to[x].back()); } st_dfs(i,x); stsize[x]+=stsize[i]; if(stsize[i]>stsize[to[x][0]]){ swap(i,to[x][0]); } } } void hld_dfs(int x,int p,int &id){ in[x]=id++; for(auto i:to[x])if(i!=p){ pathtop[i]=(i==to[x][0]?pathtop[x]:i); hld_dfs(i,x,id); } out[x]=id; } public: HeavyLightDecomposition(int n,int root=0):n(n),to(n),stsize(n),par(n),in(n),out(n),root(root),pathtop(n){} void add_edge(int u,int v){ to[u].emplace_back(v); to[v].emplace_back(u); } void build(){ st_dfs(0,-1); pathtop[root]=root; int id=0; hld_dfs(0,-1,id); } inline int get(int x)const{return in[x];} int lca(int u,int v)const{ int pu=pathtop[u],pv=pathtop[v]; while(pathtop[u]!=pathtop[v]){ if(in[pu]>in[pv])u=par[pu],pu=pathtop[u]; else v=par[pv],pv=pathtop[v]; } return (in[u]>in[v]?v:u); } void subtree_query(int u ,const function<void(int,int)> &f){ f(in[u],out[u]); } void path_query(int u,int v,const function<void(int,int)>&f){ int pu=pathtop[u],pv=pathtop[v]; while(pathtop[u]!=pathtop[v]){ if(in[u]>in[v])f(in[pu],in[u]+1),u=par[pu],pu=pathtop[u]; else f(in[pv],in[v]+1),v=par[pv],pv=pathtop[v]; } if(in[u]>in[v])swap(u,v); f(in[u],in[v]+1); } void noncommutative_path_query(int u,int v,const function<void(int,int)>&f){ int l=lca(u,v); while(pathtop[u]!=pathtop[l]){ f(in[u]+1,in[pathtop[u]]); u=par[pathtop[u]]; } if(u!=l)f(in[u]+1,in[l]+1); f(in[l],in[l]+1); if(v==l)return; vector<pair<int,int>>query; while(true){ if(pathtop[l]==pathtop[v]){ query.emplace_back(in[l]+1,in[v]+1); break; } query.emplace_back(in[pathtop[v]],in[v]+1); v=par[pathtop[v]]; } reverse(all(query)); for(auto [i,j]:query)f(i,j); } }; template<class T> struct Matrix{ vector<vector<T>>A; Matrix(int h,int w):A(h,vector<T>(w,0)){} Matrix(int n):A(n,vector<T>(n,0)){} size_t height()const{return A.size();} size_t width()const{return A[0].size();} const vector<T> &operator[](int k)const{return (A.at(k));} vector<T> &operator[](int k){return (A.at(k));} Matrix I(size_t n){ Matrix m(n); rep(i,n)m[i][i]=1; return m; } Matrix &operator+=(const Matrix &B){ size_t h=height(),w=width(); assert(h==B.height()); assert(w==B.width()); rep(i,h)rep(j,w)(*this)[i][j]+=B[i][j]; return *this; } Matrix &operator-=(const Matrix &B){ size_t h=height(),w=width(); assert(h==B.height()); assert(w==B.width()); rep(i,h)rep(j,w)(*this)[i][j]-=B[i][j]; return *this; } Matrix &operator*=(const Matrix &B){ size_t h=height(),w=B.width(),p=width(); assert(B.height()==p); vector<vector<T>>C(h,vector<T>(w,0)); rep(i,h)rep(k,p)rep(j,w)C[i][j]=(C[i][j]+(*this)[i][k]*B[k][j]); A.swap(C); return *this; } Matrix &operator^=(ll k){ assert(height()==width()); assert(k>=0); Matrix B=I(height()); while(k){ if(k&1)B*=*this; *this *= *this; k>>=1ll; } A.swap(B.A); return *this; } Matrix operator+(const Matrix &B)const{ return (Matrix(*this)+=B); } Matrix operator-(const Matrix &B)const{ return (Matrix(*this)-=B); } Matrix operator*(const Matrix &B)const{ return (Matrix(*this)*=B); } Matrix operator^(const ll k)const{ return (Matrix(*this)^=k); } T det(){ Matrix<T>b(*this); assert(this->height()==this->width()); T ret=1; rep(i,width()){ int id=-1; reps(j,i,width()){ if(b[j][i]!=0)id=j; } if(id==-1)return 0; if(i!=id){ ret*=-1; swap(b[i],b[id]); } ret*=b[i][i]; T inv=b[i][i].inv(); rep(j,width()){ b[i][j]*=inv; } reps(j,i+1,width()){ T x=b[j][i]; rep(k,width()){ b[j][k]-=b[i][k]*x; } } } return ret; } Matrix inv(){ assert(this->height()==this->width()); int n=this->height(); Matrix<T>b(*this); Matrix<T>ret=I(n); rep(i,n){ int id=-1; reps(j,i,n){ if(b[j][i]!=0)id=j; } assert(id!=-1); if(i!=id){ swap(b[i],b[id]); swap(ret[i],ret[id]); } T inv=b[i][i].inv(); rep(j,n){ b[i][j]*=inv; ret[i][j]*=inv; } rep(j,n)if(i!=j){ T x=b[j][i]; rep(k,n){ b[j][k]-=b[i][k]*x; ret[j][k]-=ret[i][k]*x; } } } return ret; } }; using mint=modint1000000007; Matrix<mint>op(Matrix<mint>a,Matrix<mint>b){return a*b;} Matrix<mint>op2(Matrix<mint>a,Matrix<mint>b){return b*a;} Matrix<mint>e(){ Matrix<mint>ret(2); ret[0][0]=ret[1][1]=1; return ret; } void SOLVE(){ int n; cin>>n; HeavyLightDecomposition hld(n*2-1); rep(i,n-1){ int a,b; cin>>a>>b; hld.add_edge(a,i+n); hld.add_edge(i+n,b); } hld.build(); int q; cin>>q; segtree<Matrix<mint>,op,e>seg(n*2-1); segtree<Matrix<mint>,op2,e>segrev(n*2-1); while(q--){ char c; cin>>c; if(c=='x'){ int i,a,b,c,d; cin>>i>>a>>b>>c>>d; int id=hld.get(i+n); Matrix<mint>nxt(2); nxt[0][0]=a; nxt[0][1]=b; nxt[1][0]=c; nxt[1][1]=d; seg.set(id,nxt); segrev.set(id,nxt); } else if(c=='g'){ int u,v; cin>>u>>v; Matrix<mint>ans(2); ans[0][0]=ans[1][1]=1; hld.noncommutative_path_query(u,v,[&](int a,int b){ if(a<b)ans*=seg.prod(a,b); else ans*=segrev.prod(b,a); }); rep(i,2)rep(j,2)cout<<ans[i][j].val()<<' ';cout<<endl; } } }