3-1899G

发布时间 2023-11-19 16:54:51作者: xxj112

题意:多次查询,每次给你数组的一个区间,和树上的一个点\(x\),问数组这个区间有没有\(x\)的子节点。

题解:
树上每个点子节点的dfs序一定大于它,并且,可以处理出每个节点,子节点dfs序的区间。
问题转化成,所查询区间有没有值在区间【xl,xr】的,可持久化树状数组,可以实现,但是会很麻烦,
考虑用树状数组解决,对查询离线处理;
代码:

点击查看代码
#include <bits/stdc++.h>
#define int long long 
using namespace std;
typedef pair<int,int> pll;
typedef tuple<int,int,int> TP;
const int N = 1e6 + 10;
int a[N];
int n,m;
vector<int> ve[N];
int w=1;
pair<int,int> p[N];//子节点的dfs序
void dfs(int x,int f) //dfs处理dfs序,和字节点的区间
{
   
   p[x].first=w;
   for(auto v:ve[x])
   {
      if(v==f) continue;
      w++;
      dfs(v,x);
   }
   p[x].second=w;
}
vector<TP> la[N];
vector<TP> ra[N];
int ans[N];
int tr[N];
int lowbit(int x)
{
   return x&(-x);
}
void add(int x,int k)
{
   while(x<=n)
   {
      tr[x]+=k;
      x+=lowbit(x);
   }
}
int ser(int x)
{
   int ans=0;
   while(x>0)
   {
      ans+=tr[x];
      x-=lowbit(x);
   }
   return ans;
}
void init()
{
   for(int i=1;i<=n;i++) ve[i].clear();
   w=1;
   for(int i=1;i<=n;i++) 
      {
         la[i].clear();
         ra[i].clear();
         tr[i]=0;
      }
}
void solve(){
   cin>>n>>m;
   init();
   int l,r,x;
   for(int i=1;i<n;i++)
   {
      cin>>l>>r;
      ve[l].push_back(r);
      ve[r].push_back(l);
   }
   dfs(1,-1);
   for(int i=1;i<=n;i++)
   {
      cin>>x; 
      a[i]=p[x].first; //数组节点转化成对应的dfs序
   }
   int xl,xr;
   for(int i=1;i<=m;i++)
   {
      cin>>l>>r>>x;
      xl=p[x].first;
      xr=p[x].second;
      //i为查询时间,xl,xr为查询节点的dfs序,
      la[l].push_back({i,xl,xr}); 
      ra[r].push_back({i,xl,xr});
   }
   //核心思路对于每个要查询的数组区间,先查询未放节点,在查询放完节点
   //两者相减不为0,则表示,数组l,r之间,有dfs序未【xl,xr】 的,既子节点存在
   for(int i=1;i<=n;i++)
   {
      for(auto [d,l,r]:la[i])
      {
         ans[d]=ser(r)-ser(l-1);
      }

      x=a[i];
      add(x,1);
      for(auto [d,l,r]:ra[i])
      {
         ans[d]-=(ser(r)-ser(l-1));
      }
   }
   for(int i=1;i<=m;i++)
   {
      if(ans[i]<0)
      {
         cout<<"YES\n";
      }
      else cout<<"NO\n";
      ans[i]=0;
   }
}
signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0 ^ 0;
}