【BZOJ4458】GTY的OJ(树上超级钢琴)
大致题意: 给你一棵树,让你求出每一个节点向上的长度在\([l,r]\)范围内的路径权值和最大的\(m\)条路径的权值总和。
关于此题的数列版本
此题的数列版本,就是比较著名的【BZOJ2006】[NOI2010] 超级钢琴一题了。
其实那道题目的思想,完全也可以套到这道题目上。
当然,如果你比较强大,写主席树等玄学算法+数据结构也是可以过的。
大致思路
首先,我们\(dfs\)一遍,求出\(sum_i\)表示编号为\(i\)的节点到根节点的权值和。
考虑预处理出\(RMQ_{i,j}\)表示编号为\(i\)的节点向上长度为\(2^j\)的路径中最小的\(sum\)。
则对于每一个节点,从它出发能得到的最大值便是\(sum_x-GetMin(x,l,r)\),其中的\(GetMin\)可以用\(RMQ\)实现\(O(logN)\)求解(\(RMQ\)是\(O(1)\)的,但由于要找父亲,就变成了\(O(logN)\))。
我们可以把它们全部扔到一个堆里,每次取出堆顶,计算贡献,然后把这个区间拆成两半重新扔回堆中(具体做法可参考上面给出的链接,这里只是简单概括)。
具体实现详见代码。
代码
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define ten(x) (((x)<<3)+((x)<<1))
#define LL long long
#define N 500000
#define INF 1e18
using namespace std;
int n,m,L,R;
class FIO
{
private:
#define Fsize 100000
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)
#define pc(ch) (putchar(ch))
int f,Top;char ch,*A,*B,Fin[Fsize],Stack[Fsize];
public:
inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void write(LL x) {if(x<0) pc('-'),x=-x;if(!x) return (void)(pc('0'));while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);}
}F;
class Class_RmqSolver
{
private:
#define LogN 20
public:
int fa[N+5][LogN],sum[N+5],Depth[N+5];
private:
struct key//存储每一个元素的信息
{
int pos,l,r,k,val;//pos表示起点,l,r存储可选择的区间,k存储当前选择的终点,val存储当前答案
key(int x=0,int y=0,int z=0,int w=0,int v=0):pos(x),l(y),r(z),k(w),val(v){}
inline friend bool operator < (key x,key y) {return x.val<y.val;}
};
priority_queue<key> q;//用一个堆进行维护
struct RMQ_data//RMQ求最小值
{
int MinPos,MinVal;
RMQ_data(int x=0,int y=0):MinPos(x),MinVal(y){}
inline friend bool operator < (RMQ_data x,RMQ_data y) {return x.MinVal<y.MinVal;}
}RMQ[N+5][LogN];
inline void Init() {for(register int i,j=1;j<LogN;++j) for(i=1;i<=n;++i) fa[i][j]=fa[fa[i][j-1]][j-1],RMQ[i][j]=min(RMQ[i][j-1],RMQ[fa[i][j-1]][j-1]);}//初始化
inline int getfa(int x,int dep)//找父亲
{
for(register int i=0;i<LogN;++i) if(dep&(1<<i)) x=fa[x][i];
return x;
}
inline RMQ_data get_min(int l,int r)//求最小值
{
register int i;register RMQ_data res=RMQ[l][0];
for(i=LogN-1;i>=0;--i) if(Depth[fa[r][i]]>=Depth[l]) res=min(res,RMQ[r][i]),r=fa[r][i];
return res;
}
public:
inline void Solve()
{
register int i,t;register LL ans=0;register RMQ_data s;register key now;
for(i=1;i<=n;++i) F.read(fa[i][0]),Depth[i]=Depth[fa[i][0]]+1;//初始化
for(i=1;i<=n;++i) F.read(sum[i]),sum[i]+=sum[fa[i][0]],RMQ[i][0]=RMQ_data(i,sum[fa[i][0]]);//统计前缀和+初始化(这样可以不用DFS)
for(Init(),F.read(m),F.read(L),F.read(R),i=1;i<=n;++i) if(Depth[i]>=L) t=min(R,Depth[i]),s=get_min(getfa(i,t-1),getfa(i,L-1)),q.push(key(i,getfa(i,t-1),getfa(i,L-1),s.MinPos,sum[i]-s.MinVal));//预处理把元素扔入堆中
while(m--)
{
now=q.top(),q.pop(),ans+=now.val;//取出堆中元素,统计答案,然后拆成两半重新扔入堆中
if(Depth[now.l]<Depth[now.k]) t=getfa(now.pos,Depth[now.pos]-Depth[now.k]+1),s=get_min(now.l,t),q.push(key(now.pos,now.l,t,s.MinPos,sum[now.pos]-s.MinVal));
if(Depth[now.r]>Depth[now.k]) t=getfa(now.pos,Depth[now.pos]-Depth[now.k]-1),s=get_min(t,now.r),q.push(key(now.pos,t,now.r,s.MinPos,sum[now.pos]-s.MinVal));
}
F.write(ans);//输出答案
}
}RmqSolver;
int main()
{
return F.read(n),RmqSolver.Solve(),0;
}
【BZOJ4458】GTY的OJ(树上超级钢琴)的更多相关文章
- 【贪心 计数 倍增】bzoj4458: GTY的OJ
倍增写挂调了半个晚上 Description 身为IOI金牌的gtyzs有自己的一个OJ,名曰GOJ.GOJ上的题目可谓是高质量而又经典,他在他的OJ里面定义了一个树形的分类目录,且两个相同级别的目录 ...
- bzoj4458 GTY的OJ (优先队列+倍增)
把超级钢琴放到了树上. 这次不用主席树了..本来以为会好写一点没想到细节更多(其实是树上细节多) 为了方便,对每个点把他的那个L,R区间转化成两个深度a,b,表示从[a,b)选一个最小的前缀和(到根的 ...
- bzoj4458: GTY的OJ
题目大意:给定一棵带点权的有根树,同时给定L,R,要求找M条链,每条链满足以下条件的情况下,要求所有链权和最大: 1.两两不相同(可以包含/相交等) 2.节点数在[L,R]间 3.其中一个端点的深度必 ...
- BZOJ 2006: [NOI2010]超级钢琴
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2613 Solved: 1297[Submit][Statu ...
- 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2473 Solved: 1211[Submit][Statu ...
- bzoj2006 noi2010 超级钢琴 主席树 + 优先队列
Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2435 Solved: 1195 Description 小 Z是一个小有名气的钢琴家,最近C博士送 ...
- 2006: [NOI2010]超级钢琴 - BZOJ
Description小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为 ...
- Bzoj 2006: [NOI2010]超级钢琴 堆,ST表
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2222 Solved: 1082[Submit][Statu ...
- NOI2010超级钢琴 2
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 1296 Solved: 606[Submit][Status ...
随机推荐
- vue-cli3.0 使用图形化界面创建和管理项目
1.打开终端输入vue ui vue ui 2.创建项目 3.选择一套预设,点击创建项目按钮 4.等待安装 5.安装完成后 6.可以添加插件 7.项目依赖管理 8.项目配置管理 9.项目任务管理 10 ...
- 低价购买 dp
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- 洛谷P5159 WD与矩阵
题目背景 WD整日沉浸在矩阵中,无法自拔-- 题目描述 WD特别喜欢矩阵,尤其是\(01\)矩阵. 一天,CX给了WD一个巨大的\(n\)行\(m\)列的\(01\)矩阵,WD发现这个矩阵每行.每列的 ...
- kvm磁盘io优化以及性能测试以及与物理机对比
ubuntu下kvm的磁盘io性能优化步骤 1.virsh shutdown wcltest2 2.virsh edit wcltest2 <driver name='qemu' type='q ...
- centos7虚拟机安装
Centos7 第1章 CENTOS 7 简介 1.1 centos的演变 启动流程sysvinit 串行启动:一次一个, 一个一个启动 并行启动:全部的一起启动 init优点 运行非常良好.主要依赖 ...
- Silverlight 创建 ImageButton
这几天一直在折腾怎么在silverlight 按钮上添加图片,直接向imagebutton那样设置成属性可以直接更改,最后到处查找资料终于搞出一个imagebutton了. <Style x:K ...
- MapReduce 二次排序
默认情况下,Map 输出的结果会对 Key 进行默认的排序,但是有时候需要对 Key 排序的同时再对 Value 进行排序,这时候就要用到二次排序了.下面让我们来介绍一下什么是二次排序. 二次排序原理 ...
- Oracle快速插入数据append
1:用merge into 进行匹配更新和插入,2: 开启并行,提高速度3: 如果可以的话加NOLOGING 不写入日志4:如果数据有规律的话,分批次执行 1.使用marge快速插入; MERGE / ...
- CentOS-7.5 解决ifconfig报错
1.报错信息:-bash: ifconfig: command not found 2.检查IP地址是否设置正常 ip addr 以上说明ip设置正常,如果没有获取到IP地址则设置一个即可,设置i ...
- Java继承改进
一.java继承改进 首先,多继承的缺点: 1.继承多个父类,父类中方法名相同,产生歧义 2.父类中方法同名,子类未覆盖,也会歧义 所以,java改进,类只能单继承,接口可以多继承 接口中只有抽象方法 ...