2018 icpc Regional Dhaka G Techland
题意:给你一颗树,查询连续的一段节点距离某一个节点的最小距离。
题解:考虑树上分块。将连续的节点分成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;
}