HZAU_1203_One Stroke(尺取+倍增)
来源:互联网 发布:成为java架构师 编辑:程序博客网 时间:2024/06/06 02:42
原题:
1203: One Stroke
Time Limit: 2 Sec Memory Limit: 1280 MB
Description
There is a complete binary tree which includes n nodes. Each node on the tree has a weight w, each edge on the tree is directed from the parent node to the child node. Give you a pen, draw from the any node along the directed edge at one stroke. It is required that the sum of those drawn nodes’ s weight is no more than k. How many node can be drawn at most in one stroke?
Input
The first line input an positive integer T(1<=T<=10)indicates the number of test cases. Next, each case occupies two lines. The first line input two positive integers n(1<=n<=10^6) and k,(1<=k<=10^9)
The second line input n integers w(1<=w <=10^3),, indicate the weight of nodes from the first level of the tree and from left to right.
Output
For each test cases, output one line with the most number of nodes can be drawn in one stroke. If any node likes this doesn’t exists, output -1.
Sample Input
1
5 6
2 3 4 1 7
Sample Output
3
题意
给你一颗完全二叉树每个节点都有一个权值,然后要你从上往下找一条链,值得链上权值的和<K,且节点数最大。思路
dfs+尺取法,从根节点开始从上往下找权值和不超过k的最大结点数。找到后此时下面增加一个结点,上面减少一个节点,看是否满足小于k,如不满足,则上面再减少一个结点。直到小于k,将此时的结点数与上一个满足小于k的状态比较,选取较大者。(基于二叉树先序遍历)用倍增法存储祖先们的结点,可以提高效率。
涉及知识及算法
尺取法:有这么一类问题,需要在给的一组数据中找到不大于某一个上限的“最优连续子序列”。于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式,比较流行的叫法是“尺取法”。倍增法:倍增法与二分法都是快速查找的方法。二分法已知目标所在区间,在区间内依次减半查找目标。倍增法未知目标所在区间,依次倍增以便快速找到目标区间。
代码
#include <bits/stdc++.h>#define inf 100000000#define met(a,b) memset(a,b,sizeof a)#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long ll;using namespace std;const int N = 1e6+5;const int M = 4e5+5;int n,m,ans;int a[N]; //a数组存储点权(点值)int sum[N],fa[N][22],dep[N];void dfs(int u,int f){ //u为第几个结点,f为u父亲结点 if(u>n)return; //如果所有结点遍历完毕,则跳出 sum[u]=sum[f]+a[u]; //sum存储路过的点权和 dep[u]=dep[f]+1; //dep数组记录二叉树深度 fa[u][0]=f; //存放父亲结点序号 for(int i=1;i<22;i++)fa[u][i]=fa[fa[u][i-1]][i-1];//(倍增法)△fa[i][j]表示i结点的第2^j祖先,1倍祖先就是父亲,2倍祖先是父亲的父亲, if(sum[u]<=m)ans=max(ans,dep[u]); //选取最大结点数//(接上行)4倍祖先就是父亲的父亲的父亲的父亲......。 else { int v=u; for(int i=21;i>=0;i--){ if(sum[u]-sum[fa[v][i]]<=m){ //快速查找满足条件的值所在区间 ans=max(ans,dep[u]-dep[fa[v][i]]); //选择较多的点 v=fa[v][i]; //△此处用意:逐级向上找父亲精确查找目标值 } } } dfs(u*2,u); dfs(u*2+1,u);}int main() { int T,x,y,v; scanf("%d",&T); for(int cas=1;cas<=T;cas++){ met(fa,0); ans=0; met(sum,0); met(dep,0); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); dfs(1,0); printf("%d\n",ans==0?-1:ans); } return 0;} /************************************************************** Problem: 1203 Language: C++ Result: Accepted Time:1291 ms Memory:99160 kb****************************************************************/
代码转载自博客园博主贱人方,附上链接http://www.cnblogs.com/jianrenfang/p/6754569.html向他表示感谢。
csdn博主我在浪里的注释给了我很大帮助,附上链接http://blog.csdn.net/qq_20200047/article/details/70861098向他表示感谢。
阅读全文
0 0
- HZAU_1203_One Stroke(尺取+倍增)
- SVG 边框(stroke)
- hzau1203——One Stroke(二叉树前序遍历+倍增求祖先)
- android Shape详解(solid,stroke...)
- 图形处理(十一)Stroke Parameterization
- 1091. Acute Stroke (30) -- DFS(三维空间)
- 图形处理(十一)Stroke Parameterization
- 后缀数组(倍增)
- hdu5296(倍增lca)
- Codeforces587C(倍增LCA)
- bzoj1787(倍增lca)
- 后缀数组(倍增)
- p1613 跑路(倍增)
- LCA模板(倍增)
- *树上倍增(LCA)
- 倍增算法(LCA)
- 【luogu1613】跑路(倍增)
- hihocoder 1232(倍增)
- 20170531现场宝
- C++中delete和delete[]的区别
- opencv 霍夫变换cvHoughLines2 cvHoughCircles cvApproxPoly
- 微信小程序实战篇-电商(一)
- baseDAO数据库链接
- HZAU_1203_One Stroke(尺取+倍增)
- LNMPA上php无法获取$_SERVER['HTTPS']的解决办法
- KOTLIN开发语言文档(官方文档) -- 入门
- linux命令
- 轮播图片的展示
- Weblogic命令行更换控制台密码
- java系统高并发解决方案(转载)
- __block和__weak修饰符的区别?
- opencv boosting学习