给你一棵 n n n个点的树,根节点是红点。有 m m m个操作分为两种:
I void queryR(int id){
int res=inf;
for(int i=id;i;i=node[top].fa){
top=node[i].top;
sz=link[top].size();
if(sz==1)res=min(res,node[i].dis+node[id].depth-node[i].depth);
else{
res=min(res,query(root[top],0,node[i].id,1)+node[i].id-(sz-1)+node[id].depth-node[i].depth);
res=min(res,query(root[top],node[i].id,sz-1,0)-node[i].id+node[id].depth-node[i].depth);
}
}
printf("%d\n",res);
}
I int query(int k,int l,int r,int op){
if(l<=s[k].l&&s[k].r<=r){
if(!op)return s[k].ml;
if(op)return s[k].mr;
}
int mid=(s[k].l+s[k].r)>>1,ret=inf;
if(l<=mid)ret=min(ret,query(s[k].ls,l,r,op));
if(r> mid)ret=min(ret,query(s[k].rs,l,r,op));
return ret;
}
I void updateR(int id){
for(int i=id;i;i=node[top].fa){
top=node[i].top;
sz=link[top].size();
if(node[i].dis>node[id].depth-node[i].depth){
node[i].dis=node[id].depth-node[i].depth;
if(sz>1)update(root[top],node[i].id,node[i].dis);
}else break;
}
}
I void update(int k,int id,int v){
if(s[k].l==s[k].r){
s[k].ml=s[k].l+v;
s[k].mr=sz-1-s[k].l+v;
return;
}
int mid=(s[k].l+s[k].r)>>1;
if(id<=mid)update(s[k].ls,id,v);
if(id> mid)update(s[k].rs,id,v);
pushUp(k);
}
然后就可以 l o g 2 log^2 log2解决问题了。
#include
#include
#include
#include
#include
#define I inline
using namespace std;
typedef long long LL;
const int Mx=1e5+10086;
const int inf=1e6;
int n,q,root[Mx];
template<typename T>
I T read(){
T ans=0,b=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')b=-1;else b=1;ch=getchar();}
while(ch>='0'&&ch<='9'){ans=ans*10+ch-48;ch=getchar();}
return ans*b;
}
class Tree{
public:
I void addEdge(int x,int y){
nex[++tot]=fir[x];fir[x]=tot;to[tot]=y;
nex[++tot]=fir[y];fir[y]=tot;to[tot]=x;
}
I void init(int n){
tot=0;
for(int i=1;i<=n;i++)lg[i]=lg[i-1]+((1<<lg[i-1])==i);
base=sqrt(n)+1;
}
I void buildTree(int x,int f){
depth[x]=depth[f]+1;
dis[x]=depth[x]-1;
fa[0][x]=f;
for(int i=1;i<=lg[depth[x]];i++)fa[i][x]=fa[i-1][fa[i-1][x]];
for(int i=fir[x];i;i=nex[i]){
int v=to[i];
if(v==f)continue;
buildTree(v,x);
}
}
I void query(int id){
int ans=dis[id];
for(int i=1;i<=top;i++)ans=min(ans,dist(id,q[i]));
printf("%d\n",ans);
}
I void update(int id){
q[++top]=id;
vis[id]=1;
dis[id]=0;
if(top==base){
addNode();
top=h=0;
memset(vis,0,sizeof vis);
}
}
protected:
int fir[Mx],nex[Mx<<1],to[Mx<<1],tot;
int fa[30][Mx],depth[Mx],lg[Mx];
int q[Mx],top,base,dis[Mx],h;
bool vis[Mx];
I int lca(int x,int y){
if(depth[x]<depth[y])swap(x,y);
while(depth[x]>depth[y])x=fa[lg[depth[x]-depth[y]]-1][x];
if(x==y)return x;
for(int i=lg[depth[x]];i>=0;i--){
if(fa[i][x]!=fa[i][y]){
x=fa[i][x];
y=fa[i][y];
}
}
return fa[0][x];
}
I void addNode(){
do{
int x=q[++h];
for(int i=fir[x];i;i=nex[i]){
int v=to[i];
if(vis[v])continue;
if(dis[v]>dis[x]+1){
dis[v]=dis[x]+1;
vis[v]=1;
q[++top]=v;
}
}
}while(h<top);
}
I int dist(int x,int y){
int f=lca(x,y);
return depth[x]+depth[y]-depth[f]*2;
}
}T;
I void init(){
n=read<int>();q=read<int>();
T.init(n);
for(int i=1;i<n;i++)T.addEdge(read<int>(),read<int>());
T.buildTree(1,0);
}
I void work(){
int op,id;
for(int i=1;i<=q;i++){
scanf("%d%d",&op,&id);
switch(op){
case 1:T.update(id);break;
case 2:T.query(id);break;
}
}
}
int main(int argv,char* argc[]){
init();
work();
}
#include
#include
#include
#include
#include
#include
#define I inline
using namespace std;
typedef long long LL;
const int Mx=1e5+10086;
const int inf=1e6;
int n,q,root[Mx];
template<typename T>
I T read(){
T ans=0,b=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')b=-1;else b=1;ch=getchar();}
while(ch>='0'&&ch<='9'){ans=ans*10+ch-48;ch=getchar();}
return ans*b;
}
class Tree{
public:
I void addEdge(int x,int y){
nex[++tot]=fir[x];fir[x]=tot;to[tot]=y;
nex[++tot]=fir[y];fir[y]=tot;to[tot]=x;
}
I void buildTree(int x,int f){
int MaxSon=-1;
node[x].depth=node[f].depth+1;
node[x].fa=f;
node[x].size=1;
for(int i=fir[x];i;i=nex[i]){
int v=to[i];
if(v==f)continue;
buildTree(v,x);
node[x].size+=node[v].size;
if(node[v].size>MaxSon)node[x].son=v,MaxSon=node[v].size;
}
}
protected:
struct Node{
int fa,son,depth,id,size,top,dis;
}node[Mx];
int fir[Mx],nex[Mx<<1],to[Mx<<1],tot;
};
class CutTree:public Tree{
public:
I void buildCutTree(int x,int top){
int si=link[top].size();
node[x].top=top;
node[x].id=si;
link[top].push_back(x);
if(!node[x].son)return;
buildCutTree(node[x].son,top);
for(int i=fir[x];i;i=nex[i]){
int v=to[i];
if(v==node[x].fa||v==node[x].son)continue;
buildCutTree(v,v);
}
}
I void updateR(int id);
I void queryR(int id);
protected:
vector<int>link[Mx];
};
class SegTree:public CutTree{
public:
#define ml minFromLeft
#define mr minFromRight
#define s segnode
I void init(){
for(int i=1;i<=n;i++)node[i].dis=inf;
node[1].dis=0;
buildTree(1,0);
buildCutTree(1,1);
for(int i=1;i<=n;i++){
int si=link[i].size();
if(node[i].top==i&&si!=1)
buildSegTree(root[i],0,si-1);
}
sz=link[1].size();
update(root[1],0,0);
}
I int query(int k,int l,int r,int op){
if(l<=s[k].l&&s[k].r<=r){
if(!op)return s[k].ml;
if(op)return s[k].mr;
}
int mid=(s[k].l+s[k].r)>>1,ret=inf;
if(l<=mid)ret=min(ret,query(s[k].ls,l,r,op));
if(r> mid)ret=min(ret,query(s[k].rs,l,r,op));
return ret;
}
I void update(int k,int id,int v){
if(s[k].l==s[k].r){
s[k].ml=s[k].l+v;
s[k].mr=sz-1-s[k].l+v;
return;
}
int mid=(s[k].l+s[k].r)>>1;
if(id<=mid)update(s[k].ls,id,v);
if(id> mid)update(s[k].rs,id,v);
pushUp(k);
}
I void updateR(int id){
for(int i=id;i;i=node[top].fa){
top=node[i].top;
sz=link[top].size();
if(node[i].dis>node[id].depth-node[i].depth){
node[i].dis=node[id].depth-node[i].depth;
if(sz>1)update(root[top],node[i].id,node[i].dis);
}else break;
}
}
I void queryR(int id){
int res=inf;
for(int i=id;i;i=node[top].fa){
top=node[i].top;
sz=link[top].size();
if(sz==1)res=min(res,node[i].dis+node[id].depth-node[i].depth);
else{
res=min(res,query(root[top],0,node[i].id,1)+node[i].id-(sz-1)+node[id].depth-node[i].depth);
res=min(res,query(root[top],node[i].id,sz-1,0)-node[i].id+node[id].depth-node[i].depth);
}
}
printf("%d\n",res);
}
private:
struct SegNode{
int ls,rs,l,r,minFromLeft,minFromRight;
}segnode[Mx<<3];
int sz,si,top;
I void buildSegTree(int &k,int l,int r){
k=++si;s[k].l=l,s[k].r=r;s[k].ml=s[k].mr=inf;
if(l==r)return;
int mid=(l+r)>>1;
buildSegTree(s[k].ls,l,mid);
buildSegTree(s[k].rs,mid+1,r);
}
I void pushUp(int k){
s[k].ml=min(s[s[k].ls].ml,s[s[k].rs].ml);
s[k].mr=min(s[s[k].ls].mr,s[s[k].rs].mr);
}
}T;
void init(){
n=read<int>();q=read<int>();
for(int i=1;i<n;i++)T.addEdge(read<int>(),read<int>());
T.init();
}
void work(){
T.update(root[1],0,0);
int op,x;
for(int i=1;i<=q;i++){
scanf("%d%d",&op,&x);
if(op==1)T.updateR(x);
if(op==2)T.queryR(x);
}
}
int main(int argv,char* argc[]){
init();
work();
}