• hdu 3717 Rescue


    Rescue

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 708    Accepted Submission(s): 167


    Problem Description
    The princess is trapped in a magic place. In this place, there are N magic stones. In order to rescue the princess, you should destroy all the stones. The N stones are in a straight line. We number them as s1, s2, ... sn from left to right. Each stone has a magic strength m1, m2, ... mn. You have a powerful skill that can do some damage to the stones. To release the skill, you should stand to the right of some stone (si). Then you throw a power ball towards left. Initially, this ball has a power of p. When it hits a stone, it will do some damage to the stone and its power will be decreased, and the ball will continue to fly left to the next stone if its power is still positive. Formally, if you stand to the right of si and the power ball's initial power is p, then the ball will do Max(0, p - (i - j) * (i - j)) damage to sj, for each j <= i. So from this formula, we can see that the damage to stone sj is only determined by the initial power of the ball and the number of stones between si and sj. A stone is destroyed if the damage you do is larger than its magic strength. Note that even if a stone is destroyed, it will not disappear; your magic ball will do damage to it and the power will be decreased by that stone. You are not strong enough so that you can release at most k magic balls. It will cost a lot of energy if the power of the magic ball is too high. So what is the minimum value of p with which you can destroy all the magic stones, with no more than k magic balls? You can choose where to release each magic ball as your will, and the power of the ball must be a positive integer.
     
    Input
    The first line is the number of cases T (T ≤ 100). For each case, the first line gives two integers n, k (1 ≤ n ≤ 50000, 1 ≤ k ≤ 100000). The second line are n integers, giving m1, m2, ... mn (1 ≤ m ≤ 109).
     
    Output
    Print minimum possible p in a line.
     
    Sample Input
    2
    1
    1 1
    3 1
    1 4 5
     
    Sample Output
    2 6
     
    Author
    HANG, Hang
     
    Source

     题意:给出n块石头,每块都有一个承受的伤害值mi,你现在需要把所有石头都销毁。你每次找最右的没有被

    销毁的石头投放魔法石,魔法石可以从右到左对石头造成伤害,加入你投放的位置的是 j ,

    那么对i 造成的伤害是max(0,p-(i-j)*(i-j)) 。对于石头i ,如果伤害累加 > mi那么就会被销毁,

    注意不会消失。最多可以投放 k次魔法石,求最小的p 

    思路:很容易想到二分p ,现在判断二分的是p 是否满足

    如果你投放一个魔法石在 j ,那么它造成的伤害范围是可以算出来的 (j - sqrt(p))~j 

    因为(i-j)^2 = i*i+j*j-2*i*j ;

    所以我们可以用 sum1记录所有的j 之和,sum2记录所有的j*j 之和,统计记录加的个数cnt。

    我们计算到 i 时,它已经受的伤害衰减就是v= sum2+i*i*cnt-2*sum1*i;

    cnt*p-v就是它已经受的伤害之和;

    这样就很容易搞了,注意伤害只是一个范围的,出了范围把它减去就好了

    还有注意对于每块石头可以投多次魔法石

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #include<map>
    #include<ctime>
    #include<bitset>
    #define LL long long
    #define ll long long
    #define INF 0x3f3f3f3f
    #define maxn 50010
    #define eps 1e-6
    #define mod 1000000007
    using namespace std;
    
    int val[maxn];
    LL add1[maxn],add2[maxn],cnt1[maxn] ;
    bool check(LL x,int n,int k )
    {
        int i,j,tt=sqrt(x+0.0) ,hehe;
        LL sum1,sum2,cnt,v ,su,ans=0;
        sum1=sum2=cnt=0;
      /*  memset(add1,0,sizeof(add1)) ;
        memset(add2,0,sizeof(add2)) ;
        memset(cnt1,0,sizeof(cnt1)) ;*/
        for( i = n ; i >= 1 ;i--)
            add2[i]=add1[i]=cnt1[i]=0;
        for( i = n ; i >= 1 ;i--)
        {
            sum1 -= add1[i] ;
            sum2 -= add2[i] ;
            cnt -= cnt1[i] ;
    
            v=sum2+(LL)i*i*cnt-2*sum1*i;
            su=cnt*x-v;
    
            if(su > val[i]) continue ;
            hehe=val[i];
            hehe -= su ;
            su = hehe/x;
            su++;
            ans+=su;
            if(ans>k) return false;
            sum1 += i*su ;
            sum2 += (LL)i*i*su ;
            cnt+=su;
            j = i-tt-1 ;
            if(j>=1)
            {
                add1[j] += i*su ;
                add2[j] += i*su*i ;
                cnt1[j]+=su;
            }
        }
        return true;
    }
    int main()
    {
        int i,n,m,j,k;
        LL L,R,ans,mid ;
        int T ;
       // freopen("in.txt","r",stdin);
        cin >> T ;
        while(T--)
        {
            scanf("%d%d",&n,&k) ;
            for( i = 1 ; i <= n;i++){
                scanf("%d",&val[i]);
            }
            R=1e12;
            L=1;
            ans=-1;
            while(L<=R)
            {
                mid=(L+R)>>1 ;
                if(check(mid,n,k))
                {
                    ans=mid;
                    R=mid-1;
                }
                else L =mid+1;
            }
            printf("%I64d
    ",ans) ;
        }
        return 0 ;
    }
    View Code
  • 相关阅读:
    入职外包一个月的感受!(读者投稿)
    作为架构风格的 REST 到底是什么
    PHP基础之查找
    PHP基础之排序
    PHP入门之数组
    PHP入门之函数
    PHP入门之流程控制
    PHP入门之类型与运算符
    DC-1靶机实战和分析
    【基础算法】 状态压缩DP---蒙德里安的梦想
  • 原文地址:https://www.cnblogs.com/20120125llcai/p/4066283.html
Copyright © 2020-2023  润新知