結果
問題 | No.399 動的な領主 |
ユーザー | kenta255 |
提出日時 | 2021-08-27 23:18:25 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 738 ms / 2,000 ms |
コード長 | 6,603 bytes |
コンパイル時間 | 3,241 ms |
コンパイル使用メモリ | 226,592 KB |
実行使用メモリ | 15,144 KB |
最終ジャッジ日時 | 2024-11-21 05:15:29 |
合計ジャッジ時間 | 10,598 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,816 KB |
testcase_02 | AC | 2 ms
6,820 KB |
testcase_03 | AC | 2 ms
6,820 KB |
testcase_04 | AC | 5 ms
6,820 KB |
testcase_05 | AC | 45 ms
6,816 KB |
testcase_06 | AC | 667 ms
14,252 KB |
testcase_07 | AC | 666 ms
14,380 KB |
testcase_08 | AC | 664 ms
13,176 KB |
testcase_09 | AC | 681 ms
14,320 KB |
testcase_10 | AC | 6 ms
6,816 KB |
testcase_11 | AC | 36 ms
6,816 KB |
testcase_12 | AC | 492 ms
15,144 KB |
testcase_13 | AC | 478 ms
14,884 KB |
testcase_14 | AC | 167 ms
13,100 KB |
testcase_15 | AC | 237 ms
13,224 KB |
testcase_16 | AC | 345 ms
14,580 KB |
testcase_17 | AC | 738 ms
14,448 KB |
testcase_18 | AC | 674 ms
14,180 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; typedef long long ll; //#define P pair<ll,ll> #define FOR(I,A,B) for(ll I = ll(A); I < ll(B); ++I) #define FORR(I,A,B) for(ll I = ll((B)-1); I >= ll(A); --I) #define TO(x,t,f) ((x)?(t):(f)) #define SORT(x) (sort(x.begin(),x.end())) // 0 2 2 3 4 5 8 9 #define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin()) //xi>=v x is sorted #define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin()) //xi>v x is sorted #define NUM(x,v) (POSU(x,v)-POSL(x,v)) //x is sorted #define REV(x) (reverse(x.begin(),x.end())) //reverse ll gcd_(ll a,ll b){if(a%b==0)return b;return gcd_(b,a%b);} ll lcm_(ll a,ll b){ll c=gcd_(a,b);return ((a/c)*b);} #define NEXTP(x) next_permutation(x.begin(),x.end()) const ll INF=ll(1e16)+ll(7); const ll MOD=1000000007LL; #define out(a) cout<<fixed<<setprecision((a)) //tie(a,b,c) = make_tuple(10,9,87); #define pop_(a) __builtin_popcount((a)) ll keta(ll a){ll r=0;while(a){a/=10;r++;}return r;} ll ketawa(ll a){ll r=0;while(a){r+=a%10;a/=10;}return r;} #define num_l(a,v) POSL(a,v) //v未満の要素数 #define num_eql(a,v) POSU(a,v) //v以下の要素数 #define num_h(a,v) (a.size() - POSU(a,v)) //vより大きい要素数 #define num_eqh(a,v) (a.size() - POSL(a,v)) //v以上の要素数 struct HL{ // 0indexed vector<int> HLvector; // 頂点の列 vector<int> root_union; // root_union[i] = HLした後 頂点 HLvector[i] の根の頂点番号 vector<int> par; // par[i]=頂点iの親 HL分解する前のグラフで1つ根に向かったやつ vector<int> index; // index[i]=j <=> HLvector[j]=i vector<int> depth; //depth[i]=頂点iの元の木での深さ void make_HLvector(const vector<int> &u,const vector<int> &v){ HLvector.clear(); root_union.clear(); int N = u.size() + 1; par.resize(N); for(int i=0;i<N;i++) par[i] = -1; auto ltof = leaf_to_root(u,v,0); vector<int> num(N,1); vector<vector<int>> G(N); for(auto e:ltof) num[e.first] += num[e.second]; for(auto e:ltof) par[e.second] = e.first; for(int i=0;i<N-1;i++){ G[u[i]].push_back(v[i]); G[v[i]].push_back(u[i]); } stack< pair<int,int> > st; st.push({0,0}); // 頂点,最も浅い頂点 while(st.size()){ int i = st.top().first; int p = st.top().second; st.pop(); HLvector.push_back(i); root_union.push_back(p); int val = 0 , big_child = 0; for(auto v:G[i]){ if(num[v] > num[i]) continue; // 親には戻らない if(num[v] > val){ val = num[v]; big_child = v; } } if(val == 0) continue; for(auto v:G[i]){ if(num[v] > num[i] || v == big_child) continue; st.push({v,v}); } st.push({big_child,p}); } index.resize(N); for(int i=0;i<N;i++){ index[ HLvector[i] ] = i; } reverse(ltof.begin(), ltof.end()); depth.resize(N); depth[0] = 0; for(auto e:ltof) depth[e.second] = depth[e.first] + 1; } vector< pair<int,int> > index_route(int u,int v){ // u,vパスを連結成分で区切った時のパスの(HLvectorの)indexを示す vector< pair<int,int> > res; while(root_union[index[u]] != root_union[index[v]]){ if(depth[ root_union[index[u]] ] < depth[ root_union[index[v]] ]) swap(u,v); int a = root_union[ index[u] ]; //u と a のindex res.push_back({ index[a] , index[u] }); u = par[a]; assert(u>=0); } res.push_back({min(index[u],index[v]),max(index[u],index[v])}); return res; } vector< pair<int,int> > leaf_to_root(const vector<int> &u,const vector<int> &v,const int root){ // return <parent,child> int yet = -1; vector<int> d(u.size()+1,yet); vector< pair<int,int> > res; queue<int> Q; Q.push(root); d[root] = 0; vector< vector<int> > G(u.size()+1); for(int i=0;i<u.size();i++){ G[u[i]].push_back(v[i]); G[v[i]].push_back(u[i]); } while( Q.size() ){ int now = Q.front(); Q.pop(); for(auto nex:G[now]){ if(d[nex]!=yet)continue; d[nex] = d[now] + 1; Q.push(nex); res.push_back( make_pair(now,nex) ); } } reverse(res.begin(), res.end()); return res;// return <parent,child> } }; template <typename T> class Lazy_Seg_Tree{ public: // 0-index // buketは区間変更の値 datは区間の答え // initial_d,initial_b は buket dat の 単位元 T make_dat_from_buket(T da, T bu, T s){//dat[k] = make_dat_from_buket(dat[k],buket[k],r-l); return da + bu * s; } T buket_to_child(T ch, T pa){// buket[2*k+1] = buket_to_child(buket[2*k+1],buket[k]); return ch + pa; } T buket_update(T bu , T x , T s){// buket[k] = buket_update(buket[k],x,r-l); return bu + x; } T dat_update(T dc1, T dc2){// dat[k] = dat_update(dat[2*k+1],dat[2*k+2]); return (dc1 + dc2); } vector<T> dat,buket; T initial_d,initial_b,M; int n; Lazy_Seg_Tree(int n0_=1,T initial_dat=1,T initial_buket=0 ,T M_=1){ initsize(n0_,initial_dat,initial_buket,M_); } void initsize(int n0,T initial_da,T initial_bu,T M_){ M = M_; initial_d = initial_da; initial_b = initial_bu; int k=1; while(k<n0)k*=2; n = k; dat.resize(2*n-1); buket.resize(2*n-1); for(int i=0;i<2*n-1;i++)dat[i]=initial_da; for(int i=0;i<2*n-1;i++)buket[i]=initial_bu; } void eval(int k,int l,int r){ if(buket[k] != initial_b){ dat[k] = make_dat_from_buket(dat[k],buket[k],r-l); if(r-l>1){ buket[2*k+1] = buket_to_child(buket[2*k+1],buket[k]); buket[2*k+2] = buket_to_child(buket[2*k+2],buket[k]); } buket[k] = initial_b; } } void operate(int a,int b, T x, int k=0,int l=0, int r=-1){ if(r<0)r=n; eval(k,l,r); if(b<=l || r<=a)return; if(a<=l && r<=b){ buket[k] = buket_update(buket[k],x,r-l); eval(k,l,r); }else{ operate(a,b,x,2*k+1,l,(l+r)/2); operate(a,b,x,2*k+2,(l+r)/2,r); dat[k] = dat_update(dat[2*k+1],dat[2*k+2]); } } T get(int a,int b,int k=0,int l=0,int r=-1){ if(r<0)r=n; if(b<=l || r<=a) return initial_d; eval(k,l,r); if(a<=l && r<=b) return dat[k]; T vl = get(a,b,2*k+1,l,(l+r)/2); T vr = get(a,b,2*k+2,(l+r)/2,r); return dat_update(vl,vr); } }; int main(){ int N; cin >> N; vector<int> u(N-1),v(N-1); FOR(i,0,N-1){ cin >> u[i] >> v[i]; u[i]--; v[i]--; } HL hl; hl.make_HLvector(u,v); Lazy_Seg_Tree<ll> sg(N,0,0,MOD); int Q; cin >> Q; ll ans = 0; while(Q--){ int a,b; cin >> a >> b; a--; b--; auto r = hl.index_route(a,b); for(auto e:r){ a = e.first; b = e.second; sg.operate(a,b+1,1,0,0,-1); } for(auto e:r){ ans += sg.get(e.first,e.second+1,0,0,-1); /*for(int i=e.first;i<=e.second;i++){ ans += sg.get(i,i+1,0,0,-1); }*/ //cout << "["<<e.first<<","<<e.second<<"]"<<endl; } } cout << ans << endl; }