标签:codeforce sum str pre pair 另一个 节点 导致 tor
??给出一棵 \(n\) 个点的树,\(m\) 次询问,每次询问给出 \(k\) 个点,问这 \(k\) 个点能否在其中某个点到根节点 \(1\) 的路径上或者与路径的距离为 \(1\)。
数据范围:\(2≤n≤2?10^{5}\) , \(1≤m≤2?10^{5}\) , \(1≤k_i≤n\) , \(\sum_{i=1}^{m}{k_i}≤2?10^5\)
??首先,要确定路径。显然,应该为深度最深的点到根节点的路径。然后,在判断其他的点是否满足要求。
??一开始的做法是,把第 \(i\) 询问中的每个点累加到其父亲节点上,然后把路径跑一遍,再剪一下枝,但最后 \(t\)在了第 \(100\) 个测试点。
??可能是因为树的形态导致,很可能每次查询的复杂度都是 \(O(n)\)。
代码如下:
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef pair<int,int>P;
const int N=2e5+5;
vector<int>pic[N];
int depth[N],par[N],vis[N];
P num[N];
void read(int &x)
{
x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch==‘-‘)
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<3)+(x<<1)+ch-‘0‘;
ch=getchar();
}
x*=f;
}
void dfs(int v,int p,int d)
{
depth[v]=d;
par[v]=p;
for(int i=0;i<pic[v].size();i++)
{
int u=pic[v][i];
if(u!=p)
dfs(u,v,d+1);
}
}
int main()
{
int n,m,u,v,k,p;
read(n),read(m);
for(int i=1;i<n;i++)
{
read(u),read(v);
pic[u].pb(v);
pic[v].pb(u);
}
dfs(1,0,0);
for(int i=1;i<=m;i++)
{
read(k);
int maxn=-1,minn=n+1;
for(int j=1;j<=k;j++)
{
read(v);
vis[v]=i;
if(depth[v]>maxn)
{
maxn=depth[v];
p=v;
}
minn=min(minn,depth[par[v]]);
if(num[par[v]].first!=i)
{
num[par[v]].first=i;
num[par[v]].second=0;
}
num[par[v]].second++;
}
int last=n+1;
while(p)
{
if(k==0||depth[p]<minn)
break;
if(vis[p]==i)
k--;
if(num[p].first==i)
k-=num[p].second;
if(vis[last]==i)
k++;
last=p;
p=par[p];
}
if(k==0)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
??因此,要借助 \(lca\) 来解决。 假设深度最深的点为点 \(p\) ,对于另一个点 \(x\) ,要使其满足要求,那么 \(lca(p,x)=x\),要么 \(lca(p,x)=x\) 的父亲节点。
??这样的复杂度就比较稳定,为 \(O(mlogn)\)。
代码:
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=2e5+5;
const int mak=20;
vector<int>pic[N];
int depth[N],par[N][mak],vn[N];
void read(int &x)
{
x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch==‘-‘)
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<3)+(x<<1)+ch-‘0‘;
ch=getchar();
}
x*=f;
}
void dfs(int v,int p,int d)
{
depth[v]=d;
par[v][0]=p;
for(int i=0;i<pic[v].size();i++)
{
int u=pic[v][i];
if(u!=p)
dfs(u,v,d+1);
}
}
void init(int n)
{
dfs(1,0,0);
for(int k=0;k+1<mak;k++)
{
for(int i=1;i<=n;i++)
par[i][k+1]=par[par[i][k]][k];
}
}
int lca(int u,int v)
{
if(depth[u]>depth[v])
swap(u,v);
for(int k=0;k<mak;k++)
{
if((depth[v]-depth[u])>>k&1)
v=par[v][k];
}
if(u==v)
return u;
for(int k=mak-1;k>=0;k--)
{
if(par[u][k]!=par[v][k])
{
u=par[u][k];
v=par[v][k];
}
}
return par[u][0];
}
int main()
{
int n,m,u,v;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
pic[u].pb(v);
pic[v].pb(u);
}
init(n);
while(m--)
{
int k=0,p,maxn=-1;
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
scanf("%d",&vn[i]);
if(depth[vn[i]]>maxn)
{
maxn=depth[vn[i]];
p=vn[i];
}
}
bool f=1;
for(int i=1;i<=k;i++)
{
int t=lca(p,vn[i]);
if(t!=vn[i]&&par[vn[i]][0]!=t)
{
f=0;
break;
}
}
if(f)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
CodeForces 1328E-Tree Queries【LCA】
标签:codeforce sum str pre pair 另一个 节点 导致 tor
原文地址:https://www.cnblogs.com/1024-xzx/p/12580534.html