“陌上人如玉,公子世无双!”|

xxj112

园龄:2年10个月粉丝:11关注:18

3-1899G

题意:多次查询,每次给你数组的一个区间,和树上的一个点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;
}

本文作者:xxj112

本文链接:https://www.cnblogs.com/xxj112/p/17842255.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   xxj112  阅读(14)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 椿 沈以诚
椿 - 沈以诚
00:00 / 00:00
An audio error has occurred.

作词 : 沈以诚

作曲 : 沈以诚

恍惚间 浸透了回忆

漫漫的回忆 存在的回忆

只看见 遗忘的笑脸

纯洁的笑脸不在身边

想实现 从前的诺言

不轻的诺言 和你的诺言

却描绘 无期限的诗

由寓意的诗刻画的线

乔木落叶 告诉我时间变迁

你仍旧倚靠石头看岁岁年年

惊觉两鬓霜白长叹一声哀怨

也不过匆匆弹指间

不在意我存在你心里面

只记得当时没有那么远

一眼朝如青丝暮成雪

美梦惊你不在眼前

我想给你一颗我的眼

倒映着曾拾起的缘

若皆是一场镜花水月

也不想忘记你的颜

唯一心愿

恍惚间 浸透了回忆

恍惚间 浸透了回忆

漫漫的回忆 存在的回忆

只看见 遗忘的笑脸

纯洁的笑脸不在身边

想实现 从前的诺言

不轻的诺言 和你的诺言

却描绘 无期限的诗

由寓意的诗刻画的线

乔木落叶 告诉我时间变迁

你仍旧倚靠石头看岁岁年年

惊觉两鬓霜白长叹一声哀怨

也不过匆匆弹指间

不在意我存在你心里面

只记得当时没有那么远

一眼朝如青丝暮成雪

美梦惊你不在眼前

我想给你一颗我的眼

倒映着曾拾起的缘

若皆是一场镜花水月

也不想忘记你的颜

唯一心愿

点击右上角即可分享
微信分享提示