結果
| 問題 |
No.650 行列木クエリ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-05-12 03:45:30 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 474 ms / 2,000 ms |
| コード長 | 18,027 bytes |
| コンパイル時間 | 5,334 ms |
| コンパイル使用メモリ | 260,312 KB |
| 最終ジャッジ日時 | 2025-01-10 10:33:39 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 10 |
コンパイルメッセージ
main.cpp: In function ‘void scan(char*)’:
main.cpp:46:27: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
46 | void scan(char a[]){ scanf("%s", a); }
| ~~~~~^~~~~~~~~
ソースコード
#pragma region Macros
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i,a,b) for(ll i=a;i<=b;++i)
#define rep(i,n) for(ll i=0;i<n;i++)
#define rep3(i,a,b) for(ll i=a;i>=b;i--)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vec vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define vec2(a,b) vector<vec>(a,vi(b))
#define vec2ll(a,b) vector<vecll>(a,vll(b))
#define vec3(a,b,c) vector<vector<vec>>(a,vec2(b,c))
#define vec3ll(a,b,c) vector<vector<vecll>>(a,vec2ll(b,c))
#define fi first
#define se second
#define all(c) begin(c),end(c)
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define lb(c,x) distance((c).begin(),lower_bound(all(c),(x)))
#define ub(c,x) distance((c).begin(),upper_bound(all(c),(x)))
using namespace std;
template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T,vector<T>,greater<T>>;
#define INT(...) int __VA_ARGS__;IN(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;IN(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;IN(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;IN(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;IN(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;IN(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;IN(__VA_ARGS__)
#define VEC(type,name,size) vector<type> name(size);IN(name)
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));IN(name)
int scan(){ return getchar(); }
void scan(int& a){ cin>>a; }
void scan(long long& a){ cin>>a; }
void scan(char &a){cin>>a;}
void scan(double &a){ cin>>a; }
void scan(long double& a){ cin>>a; }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void IN(){}
template <class Head, class... Tail> void IN(Head& head, Tail&... tail){ scan(head); IN(tail...); }
string stin() {string s;cin>>s;return s;}
template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
vi iota(int n){vi a(n);iota(all(a),0);return a;}
template<class T> void UNIQUE(vector<T> &x){sort(all(x));x.erase(unique(all(x)),x.end());}
int in() {int x;cin>>x;return x;}
ll lin() {unsigned long long x;cin>>x;return x;}
void print(){putchar(' ');}
void print(bool a){cout<<a;}
void print(int a){cout<<a;}
void print(long long a){cout<<a;}
void print(char a){cout<<a;}
void print(string &a){cout<<a;}
void print(double a){cout<<a;}
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } cout<<endl;}
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout<<" "; print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ cout<<'(';print(p.first); cout<<","; print(p.second);cout<<')'; }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ cout<<" "; print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
ll gcd(ll a, ll b){ while(b){ ll c = b; b = a % b; a = c; } return a; }
ll lcm(ll a, ll b){ if(!a || !b) return 0; return a * b / gcd(a, b); }
vector<pll> factor(ll x){ vector<pll> ans; for(ll i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
vector<int> divisor(int x){ vector<int> ans; for(int i=1;i*i<=x;i++)if(x%i==0){ans.pb(i);if(i*i!=x)ans.pb(x/i);} return ans;}
int popcount(ll x){return __builtin_popcountll(x);}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n){return uniform_int_distribution<int>(0, n)(rng);}
#define endl '\n'
#ifdef _LOCAL
#undef endl
#define debug(x) cout<<#x<<": "<<x<<endl
void err(){}
template<class T> void err(const T& t){ print(t); cout<<" ";}
template<class Head, class... Tail> void err(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); }
#else
#define debug(x)
template<class... T> void err(const T&...){}
#endif
#pragma endregion
template< typename Monoid >
struct SegmentTree {
using F = function< Monoid(Monoid, Monoid) >;
int sz;
vector< Monoid > seg;
const F f;
const Monoid M1;
SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
sz = 1;
while(sz < n) sz <<= 1;
seg.assign(2 * sz, M1);
}
void set(int k, const Monoid &x) {
seg[k + sz] = x;
}
void build() {
for(int k = sz - 1; k > 0; k--) {
seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
}
}
void update(int k, const Monoid &x) {
k += sz;
seg[k] = x;
while(k >>= 1) {
seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
}
}
Monoid query(int a, int b) {
Monoid L = M1, R = M1;
for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
if(a & 1) L = f(L, seg[a++]);
if(b & 1) R = f(seg[--b], R);
}
return f(L, R);
}
Monoid operator[](const int &k) const {
return seg[k + sz];
}
template< typename C >
int find_subtree(int a, const C &check, Monoid &M, bool type) {
while(a < sz) {
Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);
if(check(nxt)) a = 2 * a + type;
else M = nxt, a = 2 * a + 1 - type;
}
return a - sz;
}
template< typename C >
int find_first(int a, const C &check) {
Monoid L = M1;
if(a <= 0) {
if(check(f(L, seg[1]))) return find_subtree(1, check, L, false);
return -1;
}
int b = sz;
for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
if(a & 1) {
Monoid nxt = f(L, seg[a]);
if(check(nxt)) return find_subtree(a, check, L, false);
L = nxt;
++a;
}
}
return -1;
}
template< typename C >
int find_last(int b, const C &check) {
Monoid R = M1;
if(b >= sz) {
if(check(f(seg[1], R))) return find_subtree(1, check, R, true);
return -1;
}
int a = sz;
for(b += sz; a < b; a >>= 1, b >>= 1) {
if(b & 1) {
Monoid nxt = f(seg[--b], R);
if(check(nxt)) return find_subtree(b, check, R, true);
R = nxt;
}
}
return -1;
}
void print(int n){
for(int i = 0; i < n; i++){
cerr << seg[i + sz] << " " ;
}cerr << endl;
}
};
template< typename T >
struct edge{
int from, to;
T cost;
edge(int to,T cost) : from(-1), to(to), cost(cost){}
edge(int from,int to,T cost) : from(from), to(to), cost(cost){}
edge &operator=(const int &x) {
to = x;
return *this;
}
operator int() const{ return to;}
};
template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedTree = vector< Edges<T>>;
using tree = vector< vector<int> >;
tree make(int n,int offset = 1){
tree res(n);
for(int i = 0;i < n-1; i++){
int a,b; cin >> a >> b;
a -= offset,b -= offset;
res[a].emplace_back(b);
res[b].emplace_back(a);
}
return res;
}
template< typename T >
WeightedTree<T> make2(int n, int offset = 1){
WeightedTree<T> res(n);
for(int i = 0;i < n-1 ; i++){
int a,b ; cin >> a >> b;
a -= offset, b -= offset;
T c; cin >> c;
res[a].emplace_back(b,c);
res[b].emplace_back(a,c);
}
return res;
}
template< typename G >
struct HLDecomposition{
G &g;
vector<int> sz, in, out, head, rev, par;
HLDecomposition(G &g):
g(g), sz(g.size()), in(g.size()), out(g.size()), head(g.size()), rev(g.size()), par(g.size()) {}
void dfs_sz(int idx, int p){
par[idx] = p;
sz[idx] = 1;
if(g[idx].size() and g[idx][0] == p) swap(g[idx][0], g[idx].back());
for(auto &to: g[idx]){
if(to == p) continue;
dfs_sz(to,idx);
sz[idx] += sz[to];
if(sz[g[idx][0]] < sz[to]) swap(g[idx][0], to);
}
}
void dfs_hld(int idx, int par, int ×){
in[idx] = times++;
rev[in[idx]] = idx;
for(auto &to : g[idx]){
if(to == par) continue;
head[to] = (g[idx][0] == to ? head[idx] :to);
dfs_hld(to,idx,times);
}
out[idx] = times;
}
template< typename T >
void dfs_hld(int idx, int par, int ×,vector<T> &v){
in[idx] = times++;
rev[in[idx]] = idx;
for(auto &to : g[idx]){
if(to == par) {
v[in[idx]] = to.cost;
continue;
}
head[to] = (g[idx][0] == to ? head[idx] :to);
dfs_hld(to,idx,times,v);
}
out[idx] = times;
}
void build(){
dfs_sz(0,-1);
int t = 0;
dfs_hld(0,-1,t);
}
template< typename T >
vector< T > build(){
dfs_sz(0,-1);
int t = 0;
vector< T > res(g.size());
dfs_hld(0,-1,t,res);
return res;
}
int la(int v,int k){
while(1){
int u = head[v];
if(in[v] - k >= in[u]) return rev[in[v] - k];
k -= in[v] - in[u] + 1;
v = par[u];
}
}
int lca(int u,int v){
for(;; v = par[head[v]]){
if(in[u] > in[v]) swap(u,v);
if(head[u] == head[v]) return u;
}
}
template< typename T, typename Q, typename F >
T query(int u, int v, const T &e, const Q &q, const F &f, bool edge = false){
T l = e, r = e;
for(;;){
if(head[u] == head[v]) break;
if(in[u] > in[v]) {
l = f(l,q(in[head[u]],in[u] + 1));
u = par[head[u]];
}
r = f(q(in[head[v]], in[v] + 1),r);
v = par[head[v]];
}
return f(f(l,q(in[u] + edge,in[v] + 1)), r);
}
template< typename Q >
void add(int u, int v, const Q &q, bool edge = false){
for(;; v = par[head[v]]){
if(in[u] > in[v]) swap(u,v);
if(head[u] == head[v]) break;
q(in[head[v]], in[v] + 1);
}
q(in[u] + edge, in[v] + 1);
}
};
struct UnionFind {
vector< int > data;
UnionFind(int sz) {
data.assign(sz, -1);
}
bool unite(int x, int y) {
x = find(x), y = find(y);
if(x == y) return (false);
if(data[x] > data[y]) swap(x, y);
data[x] += data[y];
data[y] = x;
return (true);
}
int find(int k) {
if(data[k] < 0) return (k);
return (data[k] = find(data[k]));
}
int size(int k) {
return (-data[find(k)]);
}
};
template< class T >
struct Matrix {
vector< vector< T > > A;
Matrix() {}
Matrix(size_t n, size_t m) : A(n, vector< T >(m, 0)) {}
Matrix(size_t n) : A(n, vector< T >(n, 0)) {};
size_t height() const {
return (A.size());
}
size_t width() const {
return (A[0].size());
}
inline const vector< T > &operator[](int k) const {
return (A.at(k));
}
inline vector< T > &operator[](int k) {
return (A.at(k));
}
static Matrix I(size_t n) {
Matrix mat(n);
for(int i = 0; i < n; i++) mat[i][i] = 1;
return (mat);
}
Matrix &operator+=(const Matrix &B) {
size_t n = height(), m = width();
assert(n == B.height() && m == B.width());
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
(*this)[i][j] += B[i][j];
return (*this);
}
Matrix &operator-=(const Matrix &B) {
size_t n = height(), m = width();
assert(n == B.height() && m == B.width());
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
(*this)[i][j] -= B[i][j];
return (*this);
}
Matrix &operator*=(const Matrix &B) {
size_t n = height(), m = B.width(), p = width();
assert(p == B.height());
vector< vector< T > > C(n, vector< T >(m, 0));
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
for(int k = 0; k < p; k++)
C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]);
A.swap(C);
return (*this);
}
Matrix &operator^=(long long k) {
Matrix B = Matrix::I(height());
while(k > 0) {
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 long long k) const {
return (Matrix(*this) ^= k);
}
friend ostream &operator<<(ostream &os, Matrix &p) {
size_t n = p.height(), m = p.width();
for(int i = 0; i < n; i++) {
os << "[";
for(int j = 0; j < m; j++) {
os << p[i][j] << (j + 1 == m ? "]\n" : ",");
}
}
return (os);
}
T determinant() {
Matrix B(*this);
assert(width() == height());
T ret = 1;
for(int i = 0; i < width(); i++) {
int idx = -1;
for(int j = i; j < width(); j++) {
if(B[j][i] != 0) idx = j;
}
if(idx == -1) return (0);
if(i != idx) {
ret *= -1;
swap(B[i], B[idx]);
}
ret *= B[i][i];
T vv = B[i][i];
for(int j = 0; j < width(); j++) {
B[i][j] /= vv;
}
for(int j = i + 1; j < width(); j++) {
T a = B[j][i];
for(int k = 0; k < width(); k++) {
B[j][k] -= B[i][k] * a;
}
}
}
return (ret);
}
};
const ll MOD=1e9+7;
const int N=1100000;
template <ll Modulus> class modint {
using u64 = ll;
public:
u64 a;
constexpr modint(const u64 x = 0) noexcept : a(((x % Modulus) + Modulus)%Modulus) {}
constexpr u64 &value() noexcept { return a; }
constexpr const u64 &value() const noexcept { return a; }
constexpr modint operator+(const modint rhs) const noexcept {
return modint(*this) += rhs;
}
constexpr modint operator-(const modint rhs) const noexcept {
return modint(*this) -= rhs;
}
constexpr modint operator*(const modint rhs) const noexcept {
return modint(*this) *= rhs;
}
constexpr modint operator/(const modint rhs) const noexcept {
return modint(*this) /= rhs;
}
constexpr modint &operator+=(const modint rhs) noexcept {
a += rhs.a;
if (a >= Modulus) {
a -= Modulus;
}
return *this;
}
constexpr modint &operator-=(const modint rhs) noexcept {
if (a < rhs.a) {
a += Modulus;
}
a -= rhs.a;
return *this;
}
constexpr modint &operator*=(const modint rhs) noexcept {
a = a * rhs.a % Modulus;
return *this;
}
constexpr modint &operator/=(modint rhs) noexcept {
u64 exp = Modulus - 2;
while (exp) {
if (exp % 2) {
*this *= rhs;
}
rhs *= rhs;
exp /= 2;
}
return *this;
}
};
#define mint modint<MOD>
mint inv[N],comb[N],prd[N],invprd[N];
void calc_inv(){
inv[1]=1;
rep2(i,2,N-1){
inv[i]=inv[MOD%i]*(-MOD/i);
}
return;
}
void calc_product(){
prd[0]=prd[1]=1;
invprd[0]=invprd[1]=1;
rep2(i,2,N-1){
prd[i]=prd[i-1]*i;
invprd[i]=inv[i]*invprd[i-1];
}
return ;
}
mint cmb(int a,int b){
if(a<b)return 0;
if(a<0||b<0)return 0;
return {prd[a]*invprd[b]*invprd[a-b]};
}
mint modpow(mint x,ll n){
if(n==0) return 1;
mint res=modpow(x*x,n/2);
if(n&1) res=res*x;
return res;
}
void calc(){calc_inv();calc_product();}
using vmint = vector<mint> ;
ostream& operator<<(ostream& os, mint a){
os << a.a ;
return os;
}
signed main(){
ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);cout<<fixed<<setprecision(15);
int n = in();
tree g(n);
vector<pii> edges;
rep(i,n-1){
int a=in(),b=in();
g[a].eb(b);
g[b].eb(a);
edges.eb(a,b);
}
int Q = in();
Matrix<mint> I(2);
I = I.I(2);
HLDecomposition<tree> hld(g);
hld.build();
SegmentTree<Matrix<mint>> seg(n,[](Matrix<mint> x,Matrix<mint> y){return x*y;},I);
while(Q--){
char c;cin>>c;
if(c=='x'){
int k = in();
Matrix<mint> m(2);
rep(i,2)rep(j,2)m[i][j] = in();
if(hld.par[edges[k].first] == edges[k].se){
seg.update(hld.in[edges[k].fi],m);
}
else seg.update(hld.in[edges[k].se],m);
}
else{
int i = in(),j = in();
Matrix<mint> M = hld.query(i,j,I,[&](int x,int y){return seg.query(x,y);},[](Matrix<mint> x,Matrix<mint> y){return x*y;},true);
rep(ii,2)rep(jj,2)cout << M[ii][jj] << " ";cout<<endl;
}
}
}