結果
| 問題 |
No.529 帰省ラッシュ
|
| コンテスト | |
| ユーザー |
mugen_1337
|
| 提出日時 | 2020-10-23 21:18:48 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 529 ms / 4,500 ms |
| コード長 | 8,249 bytes |
| コンパイル時間 | 3,033 ms |
| コンパイル使用メモリ | 220,408 KB |
| 最終ジャッジ日時 | 2025-01-15 12:55:37 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 18 |
ソースコード
#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;
}
mugen_1337