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\n",qwq); }
ρωρ