P5016龙虎斗

明明是个暴力却神奇的打成了贪心(之前还打错了)

传送

我们看到数据规模,1e9,不错不错,该开long long 了

我们很容易就可以算出来龙的势力lo和虎的势力hu(变量名土求原谅),算的时候加上天降神兵后的影响

这时我们需要找到一个点,使这个点的点权增加s2,更新lo,hu,然后使lo和hu的差尽可能的小。

既然是让lo和hu的差距尽量小,我们不妨先求出来没有使用s2时他们的差,下面用a表示。接下来,我们要做的就是求使|a-s2*k|最小时,k的取值。

最好的情况当然是s2能整除a,这样|a-s2*k|=0,k=a/s2。但如果s2不能整除a,那么就需要比较一下k1=a/s2,k2=a/s2+1("/"是整除)哪个更优。

这样基础的思路就有了,但是这样体现在代码里好像很麻烦啊,又要判断整除又要讨论lo和hu哪个大还要判断最小的序号神马的,很容易出错有木有。所以我们继续思考一下。

刚才是从整除的角度来考虑的,现在我们直接使k=a/s2(k是实数),对k进行四舍五入。为什么这是对的?因为按照四舍五入得出的k肯定是要更接近a/s2的,也就会让|a-s2*k|更小。

我们再讨论lo与hu的大小关系,也就是p2在m的哪一端,如果在左端,则p2=m-k,如果在右端,p2=k+m,如果p2<1,就让p2=1(最左端就是1)

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
long long n,m,s1,s2,c[100009],lo,hu,p1;
long long read()
{
    char ch=getchar();
    long long x=0;bool flag=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')flag=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    if(flag)x=-x;
    return x;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
      c[i]=read();
    m=read();p1=read();s1=read();s2=read();
    c[p1]+=s1;
    for(int i=1;i<=n;i++)
    {
        if(i<m)
        {
            lo+=c[i]*(m-i);
        }
        if(i>m)
        {
            hu+=c[i]*(i-m);
        }
    }
    long long pwp=abs(lo-hu),qaq;
    long long qwq=round(1.0*pwp/s2);
    if(lo>hu)qwq+=m;
    if(lo<hu)qwq=m-qwq;
    if(lo==hu)qwq=m;
    if(qwq<1)qwq=1;
    printf("%d
",qwq);
}

ρωρ

原文地址:https://www.cnblogs.com/lcez56jsy/p/11097905.html