P3899 [湖南集训] 更为厉害
题意
请自行移步洛谷
分析
每次询问有两种情况:
- a 为 (a,b,c) 中深度第二大的节点,即 b 在 a 到根的路径上 (不含 a )。
对答案的贡献即为 。
- a 为 (a,b,c) 中深度最小的节点,即 b 是 a 的儿子。
记 为 a 点的 d 级儿子,此处的 d 级儿子是指在 a 子树内并且深度差等于 d 的点。
对答案的贡献即为
所以得出,维护第二种情况较为困难。但是这是可以解决的,将子树大小记在对应深度的线段树的节点上,遍历时向上线段树合并即可。
codes
#include<bits/stdc++.h> using namespace std; const int N=3e5+100; typedef long long ll; inline int read() { register char c=getchar();int x=0; while(!isdigit(c))c=getchar(); while(isdigit(c)){x=(x<<1)+(x<<3)+c-48;c=getchar();} return x; } struct edge{int y,n;}e[N<<1]; struct ques { int id; int x; }g[N]; int n,q,head[N],cnt; int siz[N],dep[N],deg[N]; ll ans[N]; vector<ques>h[N]; struct segtree { struct node{ll val;int lc,rc;}s[N<<5]; int tot,root[N<<5]; void pushup(int i){s[i].val=s[ s[i].lc ].val+s[ s[i].rc ].val;} void upd(int &i,int l,int r,int x,ll z) { if(!i)i=++tot; s[i].val+=z; if(l==r) return ; int mid=(l+r)>>1; if(x<=mid)upd(s[i].lc,l,mid,x,z); else upd(s[i].rc,mid+1,r,x,z); pushup(i); } void merg(int &i,int &j,int l,int r)// i <-- j { if(!i || !j) { i+=j; return ; } if(l==r){s[i].val+=s[j].val;return ;} int mid=(l+r)>>1; merg(s[i].lc,s[j].lc,l,mid); merg(s[i].rc,s[j].rc,mid+1,r); pushup(i); } ll que(int i,int l,int r,int x,int y) { if(!i)return 0; if(l>=x && r<=y)return s[i].val; int mid=(l+r)>>1;ll sum=0; if(x<=mid)sum+=que(s[i].lc,l,mid,x,y); if(y>mid)sum+=que(s[i].rc,mid+1,r,x,y); return sum; } void modi(int u){upd(root[u],1,n,dep[u],siz[u]-1);} void mer(int x,int y){merg(root[x],root[y],1,n);} ll ask(int x,int y) { if(dep[x]==n)return 0; return que(root[x],1,n,dep[x]+1,min(dep[x]+y,n)); } }T; void ad(int x,int y) { e[++cnt].n=head[x]; e[cnt].y=y;head[x]=cnt; } void loading(int u,int fa) { siz[u]=1;dep[u]=dep[fa]+1; for(int i=head[u],v;i;i=e[i].n) { v=e[i].y; if(v==fa)continue; loading(v,u); siz[u]+=siz[v]; } T.modi(u); } void init() { n=read();q=read(); for(int i=1,x,y;i<n;++i) { x=read();y=read(); ad(x,y);ad(y,x); } loading(1,0); ques node; for(int i=1,x,y;i<=q;++i) { x=read(); y=read(); node.id=i; node.x=y; ++deg[x]; h[x].push_back(node); } } void collect(int u,int fa) { for(int i=head[u],v;i;i=e[i].n) { v=e[i].y; if(v==fa)continue; collect(v,u); T.mer(u,v); } for(int i=0;i<deg[u];++i) { int id=h[u][i].id;ll nw=h[u][i].x; ans[id]+=(siz[u]-1ll)*min(dep[u]-1ll,nw); ans[id]+=(T.ask(u,nw)); } } void work() { collect(1,0); for(int i=1;i<=q;++i)printf("%lld\n",ans[i]); } int main() { init(); work(); return 0; }
本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18735054
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具