Processing math: 100%

礼物 倍增

礼物 倍增

【题意描述】 喵国有 n 个城市,这 n 个城市由 n-1 条道路连通,每条道路恰好 把两个城市连通,小喵喵住在 1 号城市。 每一个城市都卖该城市的独有的纪念品。第 i 个城市的纪念品价 格为 A[i]。 现在小喵喵有 q 位朋友分别要找他玩,他们分别住在 S[j]城市中 (不在 1 号城市),并且会按照最短路径走到 1 号城市。他们在来之 前,首先会购买他们所在的城市的纪念品。然后在路上,每当他们所 在的城市卖的纪念品的价格高于他们手上的所有纪念品时,他就会买 一件当地的纪念品。(当到达 1 号城市时如果符合条件也会购买)之 后把这些纪念品都送给小喵喵。在他们回去时,也会在 1 号城市购买 纪念品,之后按照原路返回,同样地,如果当地的纪念品价格高于手 中所有纪念品,那么他会买一件当地的纪念品留作纪念。(当到达 S[j]号城市时如果符合条件也会购买) 现在小喵喵想知道他们分别会送给小喵喵多少件纪念品与一个数 X 的乘积,以及他们会带回去多少件纪念品与另一个数 Y 的乘积。

【输入格式】 第 1 行三个个整数 n,X,Y,表示城市的个数,以及题目中的两 个系数。 第 2 行为用空格隔开的 n 个整数 a[i],表示每个城市的纪念品价 格。 第 3~n+1 行每行两个整数 u,v,表示 u 号城市和 v 号城市有道路 直接连接。 第 n+2 行一个整数 q,表示小喵喵的 q 次询问。 之后的 q 行,每行一个整数 s,表示他是从哪个城市出发的。

【输出格式】 一共 q 行,每行两个整数,用空格隔开,分别表示小喵喵得到的 礼物数量和和他会带回的纪念品数量。

对于返程我们直接一遍dfs,维护从根节点到节点i经过的最大价格mxg[i],如果当前节点价格大于了父亲的mxg,那么更新mxg和答案;

对于去程,对于节点u,我们要找到从叶子节点到根路径上第一个大于val[u]的节点然后进行转移,这一点可以用树上倍增找到。考试时没想到倍增直接大力树剖炸了

注意倍增中fa[1][0]=0

Copy
#include <cstdio> #include <algorithm> using namespace std; inline int read(){ char ch=getchar();int s=0; while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') s=s*10+(ch^'0'),ch=getchar(); return s; } #define MAXN 100010 int head[MAXN],nxt[MAXN*2],vv[MAXN*2],tot; inline void add_edge(int u, int v){ vv[++tot]=v; nxt[tot]=head[u]; head[u]=tot; } int n,x,y; #define LOG 19 int mxval[MAXN][LOG]; int ff[MAXN][LOG]; int mxg[MAXN],val[MAXN]; int cnt1[MAXN]; void dfs1(int u, int fa){ ff[u][0]=fa; cnt1[u]=cnt1[fa]; if(mxg[fa]<val[u]) mxg[u]=val[u],++cnt1[u]; else mxg[u]=mxg[fa]; for(int i=head[u];i;i=nxt[i]){ int v=vv[i]; if(v==fa) continue; dfs1(v, u); } } inline int work(int x, int k){ //printf("%d", x); for(int i=LOG-1;i>=0;--i) if(mxval[x][i]<=k) x=ff[x][i]; //printf("=%d\n", ff[x][0]); return ff[x][0]; } int cnt2[MAXN]; void dfs2(int u, int fa){ int res=work(u, val[u]); cnt2[u]=cnt2[res]+1; for(int i=head[u];i;i=nxt[i]){ int v=vv[i]; if(v==fa) continue; dfs2(v, u); } } int main() { n=read(),x=read(),y=read(); for(int i=1;i<=n;++i) val[i]=read(); for(int i=1;i<n;++i){ int u=read(),v=read(); add_edge(u, v); add_edge(v, u); } dfs1(1, 0); for(int i=1;i<LOG;++i) for(int j=1;j<=n;++j) ff[j][i]=ff[ff[j][i-1]][i-1]; for(int j=1;j<=n;++j) mxval[j][0]=val[ff[j][0]]; for(int i=1;i<LOG;++i) for(int j=1;j<=n;++j) mxval[j][i]=max(mxval[j][i-1], mxval[ff[j][i-1]][i-1]); dfs2(1, 0); int q=read(); while(q--){ int s=read(); printf("%d %d\n", cnt2[s]*x, cnt1[s]*y); } return 0; }
posted @   Santiego  阅读(90)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示