• [洛谷P1485] 火枪打怪


    前言

    翻远古时期的做题记录发现这道题没过,结果现在20分钟没切掉,真是丢人。

    甚至还用了对拍。

    题目

    洛谷

    讲解

    首先你不要像我一样把题看错了,溅射伤害只有一边而非两边。

    显然答案具有单调性,我们直接二分,考虑实现 (O(n)) 或者 (O(nlog_2n))( t check) 函数。

    (p-(i-j)^2) 拆成 (p-i^2+2ij-j^2) 就好了,然后从右往左贪心即可。

    可以用树状数组或者差分维护溅射伤害,一个带 (log_2n) 一个不带。

    但是我不知道带的做法能不能过。

    注意二分答案时上界的选择。

    时间复杂度 (O(nlog_2n))

    代码

    差分
    //12252024832524
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 500005;
    int n,k;
    LL a[MAXN];
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Min(T x){return x < 0 ? -x : x;}
    
    LL c[MAXN][3];//i^2 i cnt
    bool check(LL x)
    {
    	LL far = floor(sqrt(x)),lk = k;
    	for(int i = 1;i <= n;++ i) 
    		for(int j = 0;j < 3;++ j)
    			c[i][j] = 0;
    	for(int i = n;i >= 1;-- i)
    	{
    		for(int j = 0;j < 3;++ j) c[i][j] += c[i+1][j];
    		LL hp = a[i];
    		hp -= x*c[i][2]-c[i][0]+2*i*c[i][1]-c[i][2]*i*i;
    		if(hp < 0) continue;
    		LL nd = hp/x+1; lk -= nd;
    		if(lk < 0) return 0;
    		c[i][0] += nd*i*i;
    		c[i][1] += nd*i;
    		c[i][2] += nd;
    		if(i-far-1 >= 1)
    		{
    			c[i-far-1][0] -= nd*i*i;
    			c[i-far-1][1] -= nd*i;
    			c[i-far-1][2] -= nd;
    		}
    	}
    	return 1;
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); k = Read();
    	for(int i = 1;i <= n;++ i) a[i] = Read();
    	LL l = 1,r = 1e12,ans = 1e12;
    	while(l <= r)
    	{
    		LL mid = (l+r) >> 1;
    		if(check(mid)) ans = mid,r = mid-1;
    		else l = mid+1;
    	}
    	Put(ans,'
    ');
    	return 0;
    }
    

    后记

    这题紫色是不是过分了?

  • 相关阅读:
    Asp.net MVC3
    ASP.NET 路由实现页面静态化(附在线Demo和Source)
    ASP.NET MVC中Unobtrusive Ajax的妙用
    ASP.NET MVC Controller激活系统详解:IoC的应用[上篇]
    探讨大数据量处理
    提高ASP.NET性能与可伸缩性的几个个常用方法剖析
    Winform 应用
    C#利用QrCode.Net生成二维码
    MS SQL删除大数据
    由浅入深:自己动手开发模板引擎——置换型模板引擎1
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15366571.html
Copyright © 2020-2023  润新知