Shell Pyramid 极其详细的题解(二分查找)

Shell Pyramid题解


题目不放了,英文看着没啥意思,简化后就是: 给你很多堆球(如上),然后他会给一个数字N,询问第N个球在第几堆,在该堆的第几行第几个

测试用例
cin
2
19
75822050528572544
cout
4 4 3
769099 111570 11179

划重点了!
想法很简单,记录两个数组,a数组用于记录一堆球在某一行时(仔细想想,可能表达的不是很清楚),共有多少个球(1、3、6、10……),在确定了球在第几堆后,用a数组来判定具体位置
sum数组用于记录到第几堆时,共有多少个球(1、4、10、20……)

  1. 在拿到数字后,我们采用二分查找函数【lower_bound(数组开头,数组结尾,要找的数)-数组】
    ll ans1 = lower_bound(sum,sum+maxn,number)-sum;,该函数会返回一个大于等于参数val的序列值的迭代器(我上一篇博客有----stl迭代器中的二分查找),也就找到了第N个球在第几组里;
  2. 此时要进行一个操作,减去前面所有的球(比如查找到在第四组,那么就要减去前面三组的球,看还剩下多少球,从而利用a数组确定球在第四组的位置)number = number -sum[ans1-1]
  3. 然后同样的方法确定在第几行,如果确定在第四行,那么要减去前三行的球,剩下的数,就是在第四行的位置了,对吧 ll ans3 = number - a[ans2-1];
    到此为止完事了,输出即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
typedef long long ll;
int i,t;
ll a[maxn];
ll sum[maxn];
int main()
{
    ios::sync_with_stdio(false);//用于关闭cin和cout的同步,使得cin和cout效率与scanf、prinft差不多,这个题里这行没啥用,写习惯了
    a[1]=1;
    for(i=2;i<maxn;i++)
    {
        a[i]=a[i-1]+i;
    }
    sum[1]=1;
    for(i=2;i<maxn;i++)
    {
        sum[i]=sum[i-1]+a[i];
    }
    cin>>t;
    while(t--)
    {
          ll number;
          cin>>number;
          ll ans1 = lower_bound(sum,sum+maxn,number)-sum;
          number = number - sum[ans1-1];
          ll ans2 = lower_bound(a,a+maxn,number)-a;
          ll ans3 = number - a[ans2-1];
          cout<<ans1<<" "<<ans2<<" "<<ans3<<endl;
    }
    return 0;
}
  1. 下面我会拿一个例子来解析一下,答案是怎么出来的(因为我当初菜的时候,看到大神的代码只是往上面一贴,也不讲,很难看懂,所以不想让后来人也像当初的我一样狼狈)
    cin>>19
    我们取到需要用到的a和sum数组
    a【1】=1
    a【2】=3
    a【3】=6
    a【4】=10
    sum【1】=1
    sum【2】=4
    sum【3】=10
    sum【4】=20
    (1)在ll ans1 = lower_bound(sum,sum+maxn,number)-sum;过程中,Lower_bound返回第一个大于等于参数val的序列值的迭代器,也就是4
    (2)下一步,我们确定了在第四堆,那么第四堆有多少球?number = number - sum[ans1-1]; 把19-10赋给number
    (3)然后确定9在一个三角形球堆中的位置,
    ll ans2 = lower_bound(a,a+maxn,number)-a;这就不讲了,答案是4
    (4)第四排有几个球?用此时的number减去前三排的球,把9-6赋给ans3
    ll ans3 = number - a[ans2-1];
    (5)输出
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值