P11364 [NOIP2024] 树上查询 题解
P11364 [NOIP2024] 树上查询 题解
题目大意
给你一颗树,有
题目分析
看到题目后大概能猜测出是一道数据结构题,当下的数据结构题目往往是需要找到性质才能更好地维护。
学过虚树的二次排序建树后可以迅速看出区间的
在找到性质后,我们便自然地存下
于是我们便可以对每一个
那么如果该
这很明显可以三维数点,用 cdq 分治便可以轻松解决。
Code
#include <bits/stdc++.h>
#define pb emplace_back
#define lowbit(x) (x&-x)
using namespace std;
namespace fasI{
#define BF_SIZE 100000
bool IOerr=0;
inline char nc(){
static char buf[BF_SIZE],*p1=buf+BF_SIZE,*pend=buf+BF_SIZE;
if(p1==pend){
p1=buf;
pend=buf+fread(buf,1,BF_SIZE,stdin);
if(pend==p1){IOerr=1;return -1;}
}
return *p1++;
}
inline bool bla(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void rd(int &x){
char ch;
while(bla(ch=nc()));
if(IOerr){return;}
for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');
}
#undef BF_SIZE
};
using namespace fasI;
template<typename T>
inline void wr(T x)
{
if(x<0)
putchar('-'),x=-x;
if(x<=9)
putchar(x+48);
else
wr(x/10),putchar(x%10+48);
}
template<typename T>
inline void wrln(T x)
{
wr(x),putchar('\n');
}
constexpr int N=1e6+5,inf=1e9;
int n,q;
vector<int>e[N];
int dep[N],son[N],siz[N],top[N],f[N][20],fa[N],lg2[N];
inline void dfs1(int u,int ft=0)
{
fa[u]=ft;
dep[u]=dep[ft]+1;
siz[u]=1;
for(auto v:e[u])
{
if(v==ft)
continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v])
son[u]=v;
}
}
inline void dfs2(int u,int tp)
{
top[u]=tp;
if(son[u])
dfs2(son[u],tp);
for(auto v:e[u])
{
if(v==fa[u] || v==son[u])
continue;
dfs2(v,v);
}
}
inline int \operatorname{lca}(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
u=fa[top[u]];
}
return dep[u]>dep[v]?v:u;
}
inline void init()
{
lg2[1]=0;
for(int i=2;i<=n;i++)
lg2[i]=lg2[i>>1]+1;
for(int i=1;i<=n;i++)
f[i][0]=dep[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<(j-1))<=n;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
inline int rmq(int l,int r)
{
int t=lg2[r-l+1];
return max(f[l][t],f[r-(1<<t)+1][t]);
}
int idx,cur,tot;
struct node{
int id,L,R,len,dep,ans,pos;
node(){id=L=R=len=dep=ans=pos=0;}
}s[N],s1[N];
inline bool cmp1(node x,node y)
{
return x.len==y.len?x.pos<y.pos:x.len>y.len;
}
inline bool cmp2(node x,node y)
{
return x.R==y.R?x.pos<y.pos:x.R>y.R;
}
int st[N],tp;
int ans[N];
struct BIT{
int t[N];
inline void add(int x,int val)
{
if(!val)
return;
while(x<=n)
t[x]=max(t[x],val),x+=lowbit(x);
}
inline void del(int x)
{
while(x<=n)
t[x]=0,x+=lowbit(x);
}
inline int ask(int x)
{
int res=0;
while(x)
res=max(res,t[x]),x-=lowbit(x);
return res;
}
}tr;
inline void cdq(int l,int r)
{
if(l==r)
return;
int mid=l+r>>1,tot1=0;
for(int i=l;i<=mid;++i)
if(!s[i].pos)
s1[++tot1]=s[i];
for(int i=mid+1;i<=r;++i)
if(s[i].pos)
s1[++tot1]=s[i];
sort(s1+1,s1+1+tot1,cmp2);
for(int i=1;i<=tot1;i++)
if(!s1[i].pos)
tr.add(s1[i].L,s1[i].dep);
else
ans[s1[i].pos]=max(ans[s1[i].pos],tr.ask(s1[i].L));
for(int i=1;i<=tot1;++i)
if(!s1[i].pos)
tr.del(s1[i].L);
cdq(l,mid);
cdq(mid+1,r);
}
int main()
{
rd(n);
for(register int i=1;i<n;++i)
{
int u,v;
rd(u),rd(v);
e[u].pb(v),e[v].pb(u);
}
dfs1(1);
dfs2(1,1);
init();
for(register int i=1;i<n;++i)
{
node nw;
nw.id=\operatorname{lca}(i,i+1);
nw.dep=dep[nw.id];
s[++idx]=(nw);
}
s[s[1].id].L=1;
st[++tp]=1;
for(register int i=2;i<n;++i)
{
int las=i;
while(tp && s[st[tp]].dep>=s[i].dep)
las=s[st[tp]].L,tp--;
st[++tp]=i;
s[i].L=las;
}
s[n-1].R=n-1;
tp=0;
st[++tp]=n-1;
for(register int i=n-2;i>=1;--i)
{
int las=i;
while(tp && s[st[tp]].dep>=s[i].dep)
las=s[st[tp]].R,tp--;
st[++tp]=i;
s[i].R=las;
}
for(register int i=1;i<=idx;++i)
s[i].R++,s[i].len=s[i].R-s[i].L+1;
rd(q);
for(register int i=1;i<=q;++i)
{
int l,r,k;
rd(l),rd(r),rd(k);
if(k!=1)
{
idx++;
s[idx].id=0;
s[idx].L=r-k+1;
s[idx].R=l+k-1;
s[idx].len=k;
s[idx].dep=0;
s[idx].ans=0;
s[idx].pos=i;
}
else
ans[i]=(l==r)?dep[l]:rmq(l,r);
}
sort(s+1,s+1+idx,cmp1);
cdq(1,idx);
for(register int i=1;i<=q;++i)
wrln(ans[i]);
return 0;
}
Tips
别忘记