【题解】火枪打怪

在这里插入图片描述
法一.
在这里插入图片描述
法二.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
法三.(本人的作死方法,调了一晚上)
x j = p − ( i − j ) 2 x_j=p-(i-j)^2 xj=p(ij)2

x j + 1 = p − ( i − j − 1 ) 2 = p − ( i − j ) 2 − 1 + 2 ( i − j ) x_j+1=p-(i-j-1)^2=p-(i-j)^2-1+2(i-j) xj+1=p(ij1)2=p(ij)21+2(ij)

x j = x j + 1 + ( 1 + 2 i ) − 2 j x_j=x_{j+1}+(1+2i)-2j xj=xj+1+(1+2i)2j

推广一下:

x j = x j + 1 + s u m − t o t ∗ 2 j x_j=x_{j+1}+sum-tot*2j xj=xj+1+sumtot2j

用sum维护1+2i,然后递推即可。

对于超出范围的部分,需要减去递推的增量,可以令 x [ i − 1 − q ] − = m i d − ( q + 1 ) ∗ ( q + 1 ) x[i-1-q]-=mid-(q+1)*(q+1) x[i1q]=mid(q+1)(q+1) s u m sum sum, t o t tot tot部分减去所含增量即可。

#include<bits/stdc++.h>
using namespace std;
const int N=5*1e5+5;

long long n,k,a[N],b[N],x[N],y[N],der[N],der2[N];

bool check(long long mid) {
    
    
	long long tot=0,sum=0,q=sqrt(mid);
	for(int i=1;i<=n+1;i++) x[i]=0,der[i]=0,der2[i]=0;
	for(int i=n;i>=1;i--) {
    
    
		x[i]=x[i]+x[i+1]-sum+(tot-der2[i+1])*2*i;
		b[i]=a[i]-x[i];
		sum-=der[i];
		der2[i]+=der2[i+1];
		if(b[i]>=0) {
    
    
			long long t=(b[i]-1)/mid+1;
			tot+=t,sum+=t*(2*i-1),x[i]+=t*mid;
			if(i-1-q>0) x[i-1-q]-=t*(mid-(q+1)*(q+1)),der[i-1-q]+=t*(2*i-1),der2[i-1-q]+=t;
		}
	}
	return tot<=k;
}

int main() {
    
    
	scanf("%lld%lld",&n,&k);
	for(int i=1;i<=n;i++)
	    scanf("%d",&a[i]);
	long long l=1,r=1e18,ans=0;
	while(l<=r) {
    
    
		long long mid=(l+r)>>1;
		if(check(mid)) r=mid-1,ans=mid;
		else l=mid+1;
	}
	printf("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/cqbzlydd/article/details/108427795