首页 > 代码库 > 北方多校 又是一道简单题
北方多校 又是一道简单题
又是一道简单题
给出一棵有根树,每次查询给出两个节点 u 和 v,假设节点 f 是u,v的最近公共祖先,请查询以 f 为根的子树中,不在 u 到 v 这条链上且标号最小的节点。
输入格式
第一行输入正整数 T(T <= 30),表示共有T组输入数据。
对于每组数据,第一行输入两个正整数 n,m(n <= 50000,m <= 50000),表示节点数和询问数,节点编号 1 到 n,其中 1 是根节点。
接下来 n - 1 行,每行输入两个正整数u,v,表示标号为u和v的节点间有一条边。
接下来 m 行,每行输入两个正整数u,v,表示一次询问。
保证所有输入数据均合法。
输出格式
对于每次询问,输出答案。如不存在输出-1。
样例输入
13 31 21 31 21 32 3
样例输出
32-1
分析:考虑树链剖分;
把子树按dfs序可以展开到一维,然后对于链,可以将这个区间分成logn的部分,对于每个部分求最小值即可;
复杂度nlognlogn;
代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <algorithm>#include <climits>#include <cstring>#include <string>#include <set>#include <bitset>#include <map>#include <queue>#include <stack>#include <vector>#include <cassert>#include <ctime>#define rep(i,m,n) for(i=m;i<=n;i++)#define mod 1000000007#define inf 0x3f3f3f3f#define vi vector<int>#define pb push_back#define mp make_pair#define fi first#define se second#define ll long long#define pi acos(-1.0)#define pii pair<int,int>#define ls rt<<1#define rs rt<<1|1#define sys system("pause")const int maxn=1e5+10;const int N=1e5+10;using namespace std;ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}int n,m,k,t,st[maxn],ed[maxn],dep[maxn],fa[20][maxn],bel[maxn],son[maxn],pos[maxn],a[maxn],dfs_cl,mi[maxn<<2];vi e[maxn];void dfs1(int x,int y){ dep[x]=dep[y]+1; fa[0][x]=y; son[x]=1; for(int i=1;fa[i-1][fa[i-1][x]];i++) { fa[i][x]=fa[i-1][fa[i-1][x]]; } for(int i=0;i<e[x].size();i++) { int z=e[x][i]; if(z==y)continue; dfs1(z,x); son[x]+=son[z]; }}void dfs2(int x,int y,int ch){ int ma=0; pos[x]=++dfs_cl; st[x]=dfs_cl; a[dfs_cl]=x; bel[x]=ch; for(int i=0;i<e[x].size();i++) { int z=e[x][i]; if(z==y)continue; if(son[z]>son[ma])ma=z; } if(ma!=0)dfs2(ma,x,ch); for(int i=0;i<e[x].size();i++) { int z=e[x][i]; if(z==y||z==ma)continue; dfs2(z,x,z); } ed[x]=dfs_cl;}int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=19;i>=0;i--)if(dep[fa[i][x]]>=dep[y])x=fa[i][x]; if(x==y)return x; for(int i=19;i>=0;i--) { if(fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y]; } return fa[0][x];}void pup(int l,int r,int rt){ mi[rt]=min(mi[ls],mi[rs]);}void build(int l,int r,int rt){ if(l==r) { mi[rt]=a[l]; return; } int mid=l+r>>1; build(l,mid,ls); build(mid+1,r,rs); pup(l,r,rt);}int gao(int L,int R,int l,int r,int rt){ if(L==l&&R==r)return mi[rt]; int mid=l+r>>1; if(R<=mid)return gao(L,R,l,mid,ls); else if(L>mid)return gao(L,R,mid+1,r,rs); else return min(gao(L,mid,l,mid,ls),gao(mid+1,R,mid+1,r,rs));}void upd(vector<int>&a,int x,int y){ while(bel[x]!=bel[y]) { if(dep[bel[x]]<dep[bel[y]])swap(x,y); a.pb(pos[x]); a.pb(pos[bel[x]]); x=fa[0][bel[x]]; } if(pos[x]>pos[y])swap(x,y); a.pb(pos[y]); a.pb(pos[x]);}int main(){ int i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); rep(i,1,n)e[i].clear(); rep(i,1,n)rep(j,0,19)fa[j][i]=0; rep(i,1,n-1)scanf("%d%d",&j,&k),e[j].pb(k),e[k].pb(j); dfs1(1,0); dfs_cl=0; dfs2(1,0,1); build(1,n,1); while(m--) { int x,y; scanf("%d%d",&x,&y); vector<int>tmp; int lc=lca(x,y); upd(tmp,x,y); int s=st[lc],t=ed[lc]; if(lc<1||lc>n)return 0; sort(tmp.begin(),tmp.end()); int mi=1e9; for(i=0;i<tmp.size();i+=2) { if(s<=tmp[i]-1)mi=min(mi,gao(s,tmp[i]-1,1,n,1)); s=tmp[i+1]+1; } if(s<=t)mi=min(mi,gao(s,t,1,n,1)); printf("%d\n",mi==1e9?-1:mi); } } return 0;}
北方多校 又是一道简单题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。