結果
問題 | No.529 帰省ラッシュ |
ユーザー | mugen_1337 |
提出日時 | 2020-10-23 21:18:48 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 548 ms / 4,500 ms |
コード長 | 8,249 bytes |
コンパイル時間 | 3,045 ms |
コンパイル使用メモリ | 228,824 KB |
実行使用メモリ | 49,508 KB |
最終ジャッジ日時 | 2024-07-21 10:24:17 |
合計ジャッジ時間 | 10,136 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 3 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 7 ms
5,376 KB |
testcase_05 | AC | 7 ms
5,376 KB |
testcase_06 | AC | 7 ms
5,376 KB |
testcase_07 | AC | 6 ms
5,376 KB |
testcase_08 | AC | 354 ms
24,904 KB |
testcase_09 | AC | 369 ms
25,688 KB |
testcase_10 | AC | 403 ms
33,604 KB |
testcase_11 | AC | 412 ms
34,072 KB |
testcase_12 | AC | 323 ms
26,396 KB |
testcase_13 | AC | 258 ms
49,508 KB |
testcase_14 | AC | 354 ms
28,096 KB |
testcase_15 | AC | 513 ms
37,800 KB |
testcase_16 | AC | 548 ms
37,792 KB |
testcase_17 | AC | 462 ms
46,872 KB |
testcase_18 | AC | 485 ms
47,080 KB |
testcase_19 | AC | 465 ms
44,448 KB |
ソースコード
#include<bits/stdc++.h> using namespace std; #define ALL(x) begin(x),end(x) #define rep(i,n) for(int i=0;i<(n);i++) #define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl; #define mod 1000000007 using ll=long long; const int INF=1000000000; const ll LINF=1001002003004005006ll; int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; // ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;} template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;} struct IOSetup{ IOSetup(){ cin.tie(0); ios::sync_with_stdio(0); cout<<fixed<<setprecision(12); } } iosetup; template<typename T> ostream &operator<<(ostream &os,const vector<T>&v){ for(int i=0;i<(int)v.size();i++) os<<v[i]<<(i+1==(int)v.size()?"":" "); return os; } template<typename T> istream &operator>>(istream &is,vector<T>&v){ for(T &x:v)is>>x; return is; } struct LowLink{ const vector<vector<int>> &g; vector<int> used,ord,low; vector<int> articulation;// 関節点 vector<pair<int,int>> bridge;// 橋 LowLink(const vector<vector<int>> &g):g(g){} int dfs(int pre,int now,int k){ used[now]=1; ord[now]=k++; low[now]=ord[now]; bool is_articulation=false,multi_edge=false; int cnt=0; for(auto &to:g[now]){ if(to==pre and !multi_edge){ multi_edge=true; continue; } if(!used[to]){ cnt++; k=dfs(now,to,k); low[now]=min(low[now],low[to]); is_articulation|=(pre>=0 and low[to]>=ord[now]); if(ord[now]<low[to]) bridge.push_back(minmax(now,to)); }else{ // 後退辺 low[now]=min(low[now],ord[to]); } } // 根の場合子が2個以上いれば関節点 is_articulation|=(pre==-1 and cnt>1); if(is_articulation) articulation.push_back(now); return k; } void build(){ used.assign(g.size(),0); ord.assign(g.size(),0); low.assign(g.size(),0); int k=0; for(int i=0;i<(int)g.size();i++)if(!used[i]) k=dfs(-1,i,k); } bool isBridge(int u,int v){ if(ord[u]>ord[v]) swap(u,v); return ord[u]<low[v]; } }; struct TwoEdgeConnectedComponents{ LowLink LL; vector<int> comp; vector<vector<int>> tree,group; TwoEdgeConnectedComponents(const vector<vector<int>> &g):LL(g){} //点k の属する二重辺連結成分 int operator[](const int &k){ return comp[k]; } void dfs(int pre,int now,int &k){ if(pre>=0 and LL.ord[pre]>=LL.low[now]) comp[now]=comp[pre]; else comp[now]=k++; for(auto &to:LL.g[now]){ if(comp[to]==-1) dfs(now,to,k); } } void build(){ LL.build(); comp.assign(LL.g.size(),-1); int k=0; for(int i=0;i<(int)comp.size();i++){ if(comp[i]==-1) dfs(-1,i,k); } group.resize(k); for(int i=0;i<(int)LL.g.size();i++) group[comp[i]].push_back(i); tree.resize(k); for(auto &e:LL.bridge){ int u=comp[e.first],v=comp[e.second]; tree[u].push_back(v); tree[v].push_back(u); } } }; struct HLD{ vector<vector<int>> g; // u以下の部分木->[in[u],out[u]) vector<int> sz,in,out,head,rev,par,dep; HLD(vector<vector<int>> g): g(g),sz(g.size()),in(g.size()),out(g.size()),head(g.size()),rev(g.size()),par(g.size()){} void build(){ sz.assign(g.size(),0); in.assign(g.size(),0); out.assign(g.size(),0); head.assign(g.size(),0); rev.assign(g.size(),0); par.assign(g.size(),0); dep.assign(g.size(),0); dfs_sz(-1,0,0); int t=0; dfs_hld(-1,0,t); } int la(int v,int k){ while(true){ 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]]){ /* heavyな辺から先に訪問している 訪問順が遅い方を上げていけばlcaを超えない*/ if(in[u]>in[v]) swap(u,v); if(head[u]==head[v]) return u; } } int dis(int u,int v){ return dep[u]+dep[v]-2*dep[lca(u,v)]; } /* u-v のパスに関するクエリ ti: 元的な,ll付けるの忘れない q: パスの区間の求値関数,だいたいq(u,v)=seg.query(u,v) f: パスごとの結果をマージしていく関数 */ template<typename E,typename Q,typename F> E query(int u,int v,const E &ti,const Q &q,const F &f,bool edge=false){ E l=ti,r=ti; for(;;v=par[head[v]]){ if(in[u]>in[v]) swap(u,v),swap(l,r); if(head[u]==head[v]) break; l=f(q(in[head[v]],in[v]+1),l); } return f(f(q(in[u]+edge,in[v]+1),l),r); } template<typename Q> void add_path(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); } void dfs_sz(int pre,int now,int d){ dep[now]=d; par[now]=pre; sz[now]=1; if(g[now].size() and g[now][0]==pre) swap(g[now][0],g[now].back()); for(auto &to:g[now])if(to!=pre){ dfs_sz(now,to,d+1); sz[now]+=sz[to]; // 0がheavyな辺の先 if(sz[g[now][0]]<sz[to]) swap(g[now][0],to); } } void dfs_hld(int pre,int now,int ×){ in[now]=times++; rev[in[now]]=now; for(auto &to:g[now])if(to!=pre){ // lightな辺は分割され,headはtoになる head[to]=(g[now][0]==to?head[now]:to); dfs_hld(now,to,times); } out[now]=times; } }; template<typename Monoid> struct SegmentTree{ using F=function<Monoid(Monoid,Monoid)>; int sz; vector<Monoid> seg; const F f; const Monoid gen; SegmentTree(int n,const F f,const Monoid &gen):f(f),gen(gen){ sz=1; while(sz<n)sz<<=1; seg.assign(2*sz,gen); } 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],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],seg[2*k+1]); } // [a,b) Monoid query(int a,int b){ Monoid L=gen,R=gen; 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]; } }; signed main(){ int n,m,q;cin>>n>>m>>q; vector<vector<int>> g(n); rep(i,m){ int u,v;cin>>u>>v;u--,v--; g[u].push_back(v); g[v].push_back(u); } TwoEdgeConnectedComponents tecc(g); tecc.build(); HLD hld(tecc.tree); hld.build(); SegmentTree<pair<int,int>> seg(n,[&](pair<int,int> lhs,pair<int,int> rhs){return max(lhs,rhs);},make_pair(0,0)); seg.build(); vector<priority_queue<int>> ques(n); while(q--){ int t,u,v;cin>>t>>u>>v;u--; if(t==1){ int tid=tecc[u]; int id=hld.in[tid]; ques[id].push(v); seg.update(id,{ques[id].top(),id}); }else{ v--; auto res=hld.query(tecc[u],tecc[v],pair<int,int>(0,0),[&](int lw,int hi){return seg.query(lw,hi);},[&](pair<int,int> lhs,pair<int,int> rhs){return max(lhs,rhs);}); if(res.first==0) cout<<-1<<endl; else{ int id=res.second; ques[id].pop(); if(ques[id].empty()) seg.update(id,{0,id}); else seg.update(id,{ques[id].top(),id}); cout<<res.first<<endl; } } } return 0; }