http://www.elijahqi.win/2018/03/04/codeforces-342e-xenia-and-tree/
题目描述
Xenia the programmer has a tree consisting of
n
n nodes. We will consider the tree nodes indexed from 1 to
n
n . We will also consider the first node to be initially painted red, and the other nodes — to be painted blue.
The distance between two tree nodes
v
v and
u
u is the number of edges in the shortest path between
v
v and
u
u .
Xenia needs to learn how to quickly execute queries of two types:
paint a specified blue node in red;
calculate which red node is the closest to the given one and print the shortest distance to the closest red node.
Your task is to write a program which will execute the described queries.
输入输出格式
输入格式:
The first line contains two integers
n
n and
m
m
(2<=n<=10^{5},1<=m<=10^{5})
(2<=n<=105,1<=m<=105) — the number of nodes in the tree and the number of queries. Next
n-1
n−1 lines contain the tree edges, the
i
i -th line contains a pair of integers
a_{i},b_{i}
ai,bi
(1<=a_{i},b_{i}<=n,a_{i}≠b_{i})
(1<=ai,bi<=n,ai≠bi) — an edge of the tree.
Next
m
m lines contain queries. Each query is specified as a pair of integers
t_{i},v_{i}
ti,vi
(1<=t_{i}<=2,1<=v_{i}<=n)
(1<=ti<=2,1<=vi<=n) . If
t_{i}=1
ti=1 , then as a reply to the query we need to paint a blue node
v_{i}
vi in red. If
t_{i}=2
ti=2 , then we should reply to the query by printing the shortest distance from some red node to node
v_{i}
vi .
It is guaranteed that the given graph is a tree and that all queries are correct.
输出格式:
For each second type query print the reply in a single line.
输入输出样例
输入样例#1: 复制
5 4
1 2
2 3
2 4
4 5
2 1
2 5
1 2
2 5
输出样例#1: 复制
0
3
2
每sqrt(n)个就暴力做一遍 比较最小 如果到达sqrt(n)了 就全局bfs一下将这些信息更新到每个点里面 保证每次询问的都是sqrt(n)的内容 另外这里的lca我选择了rmq的离线版本 o(1)回答询问 否则复杂度可能变成n*sqrt(n)*log(n)
#include<cmath>
#include<queue>
#include<cstdio>
#include<algorithm>
#define inf 0x3f3f3f3f
#define N 110000
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x*f;
}
int cnt,h[N],n,m,nn,qq[N],top,mn[N<<1][20],dep[N],dis[N],Log[N<<1],pos[N],num;
struct node{
int y,next;
}data[N<<1];
inline void dfs(int x,int fa){
mn[++cnt][0]=x;pos[x]=cnt;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if (y==fa) continue;
dep[y]=dep[x]+1;dis[y]=dep[y];dfs(y,x);mn[++cnt][0]=x;
}
}
inline void init(){
int t=Log[cnt];
for (int j=1;j<=t;++j)
for (int i=1;i+(1<<j)-1<=cnt;++i)
if (dep[mn[i][j-1]]<dep[mn[i+(1<<j-1)][j-1]])
mn[i][j]=mn[i][j-1];else mn[i][j]=mn[i+(1<<j-1)][j-1];
}
inline int lca(int x,int y){
x=pos[x];y=pos[y];if (x>y) swap(x,y);int t=Log[y-x+1];
return dep[mn[x][t]]<dep[mn[y-(1<<t)+1][t]]?mn[x][t]:mn[y-(1<<t)+1][t];
}
inline int calc(int x,int y){return dep[x]+dep[y]-(dep[lca(x,y)]<<1);}
inline void bfs(){
queue<int>q;for (int i=1;i<=top;++i) q.push(qq[i]),dis[qq[i]]=0;top=0;
while(!q.empty()){
int x=q.front();q.pop();
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;
if (dis[x]+1<dis[y]) dis[y]=dis[x]+1,q.push(y);
}
}
}
int main(){
// freopen("cf342e.in","r",stdin);
n=read();m=read();nn=sqrt(n);Log[0]=-1;
for (int i=1;i<=n<<1;++i) Log[i]=Log[i>>1]+1;
for (int i=1;i<n;++i) {
int x=read(),y=read();
data[++num].y=y;data[num].next=h[x];h[x]=num;
data[++num].y=x;data[num].next=h[y];h[y]=num;
}dfs(1,0);init();cnt=0;
//for (int i=1;i<=n;++i) printf("%d ",dis[i]);
// printf("%d ",lca(2,5)); printf("%d ",lca(3,2)); printf("%d \n",lca(8,9));
while(m--){
int op=read(),x=read();
if (op==1) {if (top==nn) bfs();qq[++top]=x;continue;}
int tmp=inf;for (int i=1;i<=top;++i) tmp=min(tmp,calc(qq[i],x));
tmp=min(tmp,dis[x]);printf("%d\n",tmp);
}
return 0;
}