2018 icpc Regional Dhaka G Techland
阿新 • • 發佈:2020-10-20
題意:給你一顆樹,查詢連續的一段節點距離某一個節點的最小距離。
題解:考慮樹上分塊。將連續的節點分成sqrt(n)個塊,並且在這些塊中,採用樹形dp,預處理出距離到每一個節點的最小距離。對於塊內的部分O(1)的查詢。其他的部分,採用樹上dfs序,O(1)查詢LCA,暴力搞。(碼量稍大)
#include <bits/stdc++.h> using namespace std; #define fi first #define se second #define MP make_pair typedef pair<int,int> PII; const int N = 100005; const int M = 21; const int bSize = 300; const int INF = 0x3f3f3f3f; int head[N], Next[N<<1], to[N<<1], tol; int n, q, fa[N], dep[N], belong[N], bL[N], bR[N]; PII seg[N]; void addAdge(int u, int v){ Next[++tol]=head[u];to[tol]=v;head[u]=tol; Next[++tol]=head[v];to[tol]=u;head[v]=tol; } inline void chmin(int& x, int y){ if(y<x)x=y; } struct LCA{ int L[N<<1], dfn, id[N<<1]; struct RMQ{ int stTable[N<<1][M]; int lg2[N<<1], depth[N<<1]; void init(int x){ for(int i=2;i<=x;++i)lg2[i]=lg2[i>>1]+1; for(int i=1;i<=x;++i){ stTable[i][0]=i; } for(int i=1;i<=20;++i){ for(int j=1;j+(1<<i)<=x;++j){ stTable[j][i]=depth[stTable[j][i-1]]<depth[stTable[j+(1<<i-1)][i-1]]?stTable[j][i-1]:stTable[j+(1<<i-1)][i-1]; } } } int query(int x, int y){ if(x>y)swap(x,y); int len=lg2[y-x+1]; return depth[stTable[x][len]]<depth[stTable[y-(1<<len)+1][len]]?stTable[x][len]:stTable[y-(1<<len)+1][len]; } }st; void dfs(int u){ //cout<<"n: "<<n<<" "<<u<<endl; L[++dfn]=u; id[u]=dfn; st.depth[dfn]=dep[u]; for(int e=head[u];e;e=Next[e]){ int v=to[e]; if(v==fa[u])continue; fa[v]=u; dep[v]=dep[u]+1; dfs(v); L[++dfn]=u; st.depth[dfn]=dep[u]; } } void init(){ dfn=0; fa[1]=1; dep[1]=0; dfs(1); st.init(2*n-1); } inline int query(int u, int v){ return L[st.query(id[u],id[v])]; } inline int dis(int u, int v){ return dep[u]+dep[v]-2*dep[query(u,v)]; } }qry; struct bQuery{ int f[N]; void init(){ for(int i=1;i<=n;++i){ f[i]=INF+INF; } } void dfs(int u){ for(int e=head[u];e;e=Next[e]){ int v=to[e]; if(v==fa[u])continue; dfs(v); chmin(f[u],f[v]); } } void dfs1(int u){ f[u]-=2*dep[u]; chmin(f[u],f[fa[u]]); for(int e=head[u];e;e=Next[e]){ int v=to[e]; if(v==fa[u])continue; dfs1(v); } } void get(int x){ chmin(f[x],dep[x]); } void solve(){ dfs(1); dfs1(1); } }bInfo[205]; void clr(){ memset(head,0,sizeof head); tol=0; memset(seg,-1,sizeof seg); } int bruteForce(int nd, int l, int r){ int res=INF; for(int i=l;i<=r;++i){ chmin(res,qry.dis(nd,i)); } return res; } int getAns(int nd, int p){ if(seg[p].fi==-1)return INF; int res=INF; if(belong[seg[p].fi]==belong[seg[p].se]){ chmin(res,bruteForce(nd,seg[p].fi,seg[p].se)); }else{ int l=seg[p].fi, r=seg[p].se; chmin(res,bruteForce(nd,l,bR[belong[l]])); for(int i=belong[l]+1;i<belong[r];++i){ chmin(res,bInfo[i].f[nd]+dep[nd]); } chmin(res,bruteForce(nd,bL[belong[r]],r)); } return res; } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); for(int i=1;i<=100000;++i){ belong[i]=(i-1)/bSize+1; if(i==1||belong[i]!=belong[i-1])bL[belong[i]]=i; bR[belong[i]]=i; } int _;cin>>_; int kase=1; while(_--){ clr(); cin>>n; for(int i=1;i<n;++i){ int u, v; cin>>u>>v; addAdge(u,v); } qry.init(); for(int i=1;i<=belong[n];++i)bInfo[i].init(); for(int i=1;i<=n;++i){ bInfo[belong[i]].get(i); } for(int i=1;i<=belong[n];++i){ bInfo[i].solve(); } cin>>q; int op, l, r, x, m, p; cout<<"Case "<<kase++<<":"<<endl; while(q--){ cin>>op; if(op==1){ cin>>x>>l>>r; seg[x]=MP(l,r); }else if(op==2){ cin>>x; seg[x]=MP(-1,-1); }else{ int res=INF; cin>>x>>m; for(int i=1;i<=m;++i){ cin>>p; chmin(res,getAns(x,p)); } if(res>=INF)res=-1; cout<<res<<endl; } } } return 0; }