考虑点分树,找到最浅的满足条件的点,那么所有连通块符合条件的一定能以它为根来统计到。
考虑一个点 y 满足能作为颜色集合中(但不一定对答案贡献),显然是 x→y 的路径所经过的点都满足那个偏序关系。
转化为二位偏序即可,数颜色 HH 的项链,大致按 r 排序,维护最大的 l 来贡献。
哈哈,我不会二位偏序()
节省空间的话可以在建立点分树时就搞当前重心答案。
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
int rd() {
int f=1,sum=0; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
#define inf (int)(2e9)
#define N (int)(1e5+5)
struct node {
int l,r,id;
node(int lx,int rx,int idd) {
l=lx; r=rx; id=idd;
}
};
vector<int>g[N];
vector<node>Q[N],q,vec;
bool vis[N],used[N];
int n,m,ans[N],pre[N],sum[N],col[N],mi,rt,nwsum,sz[N];
int lowbit(int x) {
return x&(-x);
}
void add(int x,int v) {
if(x<=0) return ;
while(x<=n) sum[x]+=v,x+=lowbit(x);
}
int qry(int x) {
if(x<=0) return 0;
int res=0;
while(x) res+=sum[x],x-=lowbit(x);
return res;
}
void fd_rt(int x,int ff) {
sz[x]=1; int qwq=0;
for(int y:g[x]) {
if(vis[y]||y==ff) continue;
fd_rt(y,x); sz[x]+=sz[y];
qwq=max(qwq,sz[y]);
}
qwq=max(qwq,nwsum-sz[x]);
if(qwq<mi) mi=qwq,rt=x;
}
void dfs(int x,int ff,int l,int r) {
vec.pb(node(l,r,col[x]));
for(auto qwq:Q[x]) {
if(!used[qwq.id]&&qwq.l<=l&&qwq.r>=r) {
used[qwq.id]=1; q.pb(node(qwq.l,qwq.r,qwq.id));
}
}
for(int y:g[x]) {
if(vis[y]||y==ff) continue;
dfs(y,x,min(l,y),max(r,y));
}
}
bool cmp(const node &x,const node &y) {
return x.r<y.r;
}
void cal(int x) {
vec.clear(); q.clear();
dfs(x,0,x,x);
sort(vec.begin(),vec.end(),cmp);
sort(q.begin(),q.end(),cmp);
for(int i=0,j=0;i<q.size();i++) {
while(j<vec.size()&&vec[j].r<=q[i].r) {
if(vec[j].l>pre[vec[j].id]) {
add(pre[vec[j].id],-1);
add(vec[j].l,1);
pre[vec[j].id]=vec[j].l;
}
++j;
}
ans[q[i].id]=qry(q[i].r)-qry(q[i].l-1);
}
for(int i=0;i<vec.size();i++) {
add(pre[vec[i].id],-1); pre[vec[i].id]=0;
}
}
void solve(int x) {
vis[x]=1; cal(x);
for(int y:g[x]) {
if(vis[y]) continue;
mi=inf; nwsum=sz[y]; fd_rt(y,0);
solve(rt);
}
}
int main() {
n=rd(); m=rd();
for(int i=1;i<=n;i++) col[i]=rd();
for(int i=1;i<n;i++) {
int x=rd(),y=rd();
g[x].pb(y); g[y].pb(x);
}
for(int i=1;i<=m;i++) {
int x=rd(),y=rd(),z=rd();
Q[z].pb(node(x,y,i));
}
mi=inf; rt=0; nwsum=n; fd_rt(1,0);
solve(rt);
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】