题目给出n个点,只有n-1条边,而且都是连通的,那么就可以得出是一棵树。
那就变成了裸的树剖。
套模板,完事。
#include<stdio.h>
#include<algorithm>
#include<string>
#include<string.h>
#include<queue>
#include<vector>
#include<stack>
#include<math.h>
#include<map>
#include<iostream>
using namespace std;
#define maxn 300050
struct edge
{
int en,next;
}E[maxn*2];
struct node
{
int l;
int r;
int smin;
}tree[maxn*8];
int a[maxn];
int dep[maxn]; //节点深度
int fa[maxn]; //节点父亲
int siz[maxn]; //以V为跟的节点数目
int son[maxn]; //V节点的重儿子
int p[maxn],fp[maxn]; //p[v],节点v在线段树中的位置,fp[v]是p的反向映射
int top[maxn]; // v节点的重链的顶端
int head[maxn],cnt,pos,n,q; //邻接表
void addedge(int st,int en)
{
E[cnt].en=en;
E[cnt].next=head[st];
head[st]=cnt;
cnt++;
}
void inti()
{
cnt=0;pos=0;
memset(son,-1,sizeof(son));
memset(a,0,sizeof(a));
memset(dep,0,sizeof(dep));
memset(fa,0,sizeof(fa));
memset(p,0,sizeof(p));
memset(siz,0,sizeof(siz));
memset(head,-1,sizeof(head));
}
void dfs1(int u,int f,int d)
{
dep[u]=d;
fa[u]=f;
siz[u]=1;
for(int i=head[u];i!=-1;i=E[i].next)
{
int v=E[i].en;
if(v!=f)
{
dfs1(v,u,d+1);
siz[u] += siz[v];
if(son[u]==-1||siz[v]>siz[son[u]])
son[u]=v;
}
}
}
void pushup(int id)
{
tree[id].smin=min(tree[id*2].smin,tree[id*2+1].smin);
}
void build(int id,int l,int r)
{
tree[id].l=l;
tree[id].r=r;
if(l==r)
{
tree[id].smin=1;
return ;
}
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
pushup(id);
}
void update(int id,int x,int v)
{
int l=tree[id].l;
int r=tree[id].r;
int mid=(l+r)/2;
if(l==r)
{
tree[id].smin=v;
return ;
}
if(l<=x&&x<=mid)
update(id*2,x,v);
else if(mid<x&&x<=r)
update(id*2+1,x,v);
pushup(id);
}
int querymin(int id,int x,int y)
{
int l=tree[id].l;
int r=tree[id].r;
int mid=(l+r)/2;
if(x<=l&&r<=y)
return tree[id].smin;
if(y<l||x>r)
return 1e9;
return min(querymin(id*2,x,y),querymin(id*2+1,x,y));
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=pos++;
fp[p[u]]=u;
if(son[u]==-1)
return ;
getpos(son[u],sp);
for(int i=head[u];i!=-1;i=E[i].next)
{
int v=E[i].en;
if(v!=son[u]&&v!=fa[u])
getpos(v,v);
}
}
int findmin(int u,int v)
{
int f1=top[u],f2=top[v];
int ret=1e9;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(u,v);
}
ret=min(ret,querymin(1,p[f1],p[u]));
u=fa[f1];
f1=top[u];
}
if(dep[u]>dep[v])
swap(u,v);
return min(ret,querymin(1,p[u],p[v]));
}
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
inti();
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs1(1,0,0);
getpos(1,1);
build(1,0,pos-1);
while(q--)
{
int s,x,y;
scanf("%d",&s);
if(s==1)
{
scanf("%d%d",&x,&y);
int ans=findmin(x,y);
if(ans==1)
printf("YES\n");
else
printf("NO\n");
}
else if(s==2)
{
scanf("%d",&x);
update(1,p[x],1);
}
else
{
scanf("%d",&x);
update(1,p[x],0);
}
}
}
return 0;
}
本文详细介绍了一种基于树结构的数据处理算法——树剖算法。通过构建特定的数据结构来优化查询路径最小值的问题,适用于解决计算机科学中涉及树形结构的问题。
1万+

被折叠的 条评论
为什么被折叠?



