@xiaoziyao
2020-11-15T10:41:23.000000Z
字数 2429
阅读 1030
解题报告
吐槽:好奇怪呀,为什么交了两份相同的代码一份AC一份WA,不应该返回相同的答案吗。
操作分块。
我们设定一个阈值,对操作序列每个操作分一块。
对于每一次询问,我们对红点分类讨论:
具体地,每跨越一次块,我们就把这个块内所有的红点bfs一遍,更新它们到所有点的距离,这是的,但是由于只会跨越次块,所以总复杂度为。
对于在这个块内的红点,我们枚举它们,然后用ST表的的lca求距离,这样我们的复杂度为,总复杂度为。
故时间复杂度为:,很显然取时复杂度较优,为。
分块常数小,加了个快读就到最优解了。
#include<stdio.h>
#include<math.h>
#define inf 1000000000
const int maxn=100005,maxm=200005,maxk=20,maxt=405,maxq=100005;
int n,m,e,qs,t,now;
int start[maxn],to[maxm],then[maxm],lg[maxn<<1],ST[maxn<<1][maxk],dep[maxn],in[maxn],bl[maxt],br[maxt],opt[maxq],k[maxq],dis[maxn],q[maxn];
inline int min(int a,int b){
return a<b? a:b;
}
inline int calc(int a,int b){
return dep[a]<dep[b]? a:b;
}
inline void swp(int &a,int &b){
a+=b,b=a-b,a-=b;
}
inline void add(int x,int y){
then[++e]=start[x],start[x]=e,to[e]=y;
}
void dfs(int x,int last){
dep[x]=dep[last]+1,in[x]=++qs,ST[qs][0]=x;
for(int i=start[x];i;i=then[i]){
int y=to[i];
if(y==last)
continue;
dfs(y,x);
ST[++qs][0]=x;
}
}
void getST(){
lg[0]=-1;
for(int i=1;i<=qs;i++)
lg[i]=lg[i/2]+1;
for(int i=1;i<=18;i++)
for(int j=1;j+(1<<i)-1<=qs;j++)
ST[j][i]=calc(ST[j][i-1],ST[j+(1<<(i-1))][i-1]);
}
int lca(int a,int b){
if(in[a]>in[b])
swp(a,b);
int l=in[a],r=in[b],k=lg[r-l+1];
return calc(ST[l][k],ST[r-(1<<k)+1][k]);
}
int getdis(int a,int b){
int c=lca(a,b);
return dep[a]+dep[b]-2*dep[c];
}
void bfs(int a,int b){
qs=0;
if(a==-1)
q[++qs]=1;
else for(int i=a;i<=b;i++)
if(opt[i]==1)
q[++qs]=k[i];
int now=1;
while(now<=qs){
int x=q[now];
now++;
for(int i=start[x];i;i=then[i]){
int y=to[i];
if(dis[y]<=dis[x]+1)
continue;
dis[y]=dis[x]+1,q[++qs]=y;
}
}
}
int query(int x,int a,int b){
int res=dis[x];
for(int i=a;i<=b;i++)
if(opt[i]==1)
res=min(res,getdis(x,k[i]));
return res;
}
void read(int &x){
char c=getchar();
x=0;
for(;c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar())
x=x*10+c-48;
}
int main(){
read(n),read(m);
for(int i=1;i<n;i++){
int x,y;
read(x),read(y);
add(x,y),add(y,x);
}
dfs(1,0),getST();
t=sqrt(m);
for(int i=1;i<=t;i++)
bl[i]=br[i-1]+1,br[i]=i*t;
if(br[t]<m)
t++,bl[t]=bl[t-1]+1,br[t]=m;
for(int i=1;i<=n;i++)
dis[i]=inf;
int last=1;
dis[1]=0,bfs(-1,-1);
for(int i=1;i<=m;i++){
if(i>br[last])
bfs(bl[last],br[last]),last++;
read(opt[i]),read(k[i]);
if(opt[i]==1)
dis[k[i]]=0;
if(opt[i]==2)
printf("%d\n",query(k[i],bl[last],i));
}
return 0;
}