CSU2146

Description

总所周知,CSU没有金字塔,但在世界某地有一座神奇的金字塔。

神奇的金字塔位于N*N的网格地上。

第0分钟时,金字塔底面很小,只占据(x,y) 这个格子,之后每过一分钟,金字塔会长大,就算超过边界也会继续长大,不过边界外是无限深渊,所以超过边界的部分不算占据的面积,而且由于是无限深渊,不需要考虑什么时候被填满的问题。

那么现在问题来了,至少在第几分钟网格上才至少有C个格子被金字塔占据。

Input

每组数据每一行有4个整数,N,X,Y,C

其中,n,x,y,c<=109,c<=n2

Output

对于每组数据,输出一行

一行仅包含一个整数,表示至少过几分钟图上才至少会有C个格子被占据

Sample Input

9 3 8 10

Sample Output

2

Hint

 

思路:这题第一次使用bfs,果然TLE了。

然后观察发现,格子数量的增长是有规律的,给定时间,是可以算出当前时刻下格子的数量,然后要减去超出边界的格子,加上减去两次的格子数量(一直卡在这里,最后是参考AC代码)。而给定时间可以想到二分法寻找最短时间。

假定初始格子所在的位置为(X,Y),经过的时间为t,则格子的数量为1+t * t * 2 + 2 * t

格子距离上下左右的边界分别为:X-1,N-X,Y-1,N-Y

超出边界部分的面积也很容易求得(按1,3,5,7,...,2k+1的规律增长),是一个平方数

往上超出边界的格子数为:^{(t - (X - 1))}(t - (X - 1))^{2};往下超出边界的格子数量为:(t-(N-X))^{2}(左边和右边同理)

然后就是求多减去的面积(重叠部分):

假设红色的为X-1,绿色的为Y-1,则红色加绿色的为t,t必须要大于红色的线+绿色的线+1才会有重叠部分的方格(画方格会更好理解),其它三个方向同理。这个重叠部分的面积为一个等差数列(1,1+2,1+2+3,...)

 

#include<cstdio>
#include<string.h>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#include<set>
#include<algorithm>
using namespace std;

long long N, X, Y, C;

int main()
{
    while (scanf("%lld %lld %lld %lld", &N, &X, &Y, &C) != EOF)
    {
        long long sum = 0L, ans = 0L;
        long long l = 0L, r = N * 2 - 1;

        long long ts = X - 1, tx = N - X;
        long long tz = Y - 1, ty = N - Y;

        while (l < r)
        {
            long long mid = (l + r) / 2;
            sum = mid * mid * 2 + 2 * mid + 1;

            //减去超出范围的面积
            if (mid > ts)
                sum -= (mid - ts) * (mid - ts);
            if (mid > tx)
                sum -= (mid - tx) * (mid - tx);
            if (mid > tz)
                sum -= (mid - tz) * (mid - tz);
            if (mid > ty)
                sum -= (mid - ty) * (mid - ty);

            //加上可能多减的面积
            if (mid > ts + tz + 1)
                sum += (mid - ts - tz - 1) * (mid - ts - tz) / 2;
            if (mid > tz + tx + 1)
                sum += (mid - tz - tx - 1) * (mid - tz - tx) / 2;
            if (mid > tx + ty + 1)
                sum += (mid - tx - ty - 1) * (mid - tx - ty) / 2;
            if (mid > ty + ts + 1)
                sum += (mid - ty - ts - 1) * (mid - ty - ts) / 2;

            if (sum >= C)   //在mid时间内占据超过C个格子,时间可以继续缩短
            {
                ans = mid;
                r = mid;
            }
            else
                l = mid + 1;
        }
        printf("%lld\n", ans);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值