gmoj 6845. 【2020.11.02提高组模拟】梯度弥散
6845. 【2020.11.02提高组模拟】梯度弥散
Solution
考虑二分答案
二分后直接贪心操作
但暴力操作的话时间复杂度\(O(nk\ \cdot log(V))\)显然无法接受
考虑差分
c=0与c=1的情况都很好做,
伤害\(\left\{\begin{matrix} c=0:1\\ c=1:(x+i)-j \end{matrix}\right.\)
其中i是刚开始攻击的位置,j为当前处理的位置
此时考虑c=2的情况(有多种方法,这里介绍一种)
此时伤害值可以表示为$(x+i-j)^2
\((x+i-j)^2=(x+i)^2\cdot j^0-2\cdot j\cdot(x+i)+j^2\)
我们可以分别差分维护变量前面的系数
这种维护方法也可以推广到维护c=0及c=1的情况
完结撒花
Code
#include <cstdio>
#define N 100010
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int num,n,c,k,i,j,l,r,mid,ans,last,add,s[N],a[4];
long long t,b[N][4];
int min(int x,int y){return x<y?x:y;}
int main()
{
open("dispersion");
scanf("%d%d%d%d",&num,&n,&c,&k);
for (i=1;i<=n;i++)
scanf("%d",&s[i]);
l=0;r=100000;
while (l<r)
{
mid=(l+r)/2;ans=0;
a[0]=a[1]=a[2]=0;
for (i=1;i<=n;i++)
{
t=s[i];
for (j=0;j<=2;j++)
a[j]+=b[i][j],b[i][j]=0;
t-=a[0]+a[1]*i+a[2]*i*i;
if (t<=0) continue;
add=min(i+mid+1,n+1);
if (!c)
{
last=t;
b[add][0]-=last;
a[0]+=last;
}
if (c==1)
{
last=t/(mid)+(t%(mid)!=0);
b[add][0]-=1ll*(i+mid)*last;
b[add][1]+=last;
a[0]+=1ll*(i+mid)*last;
a[1]-=last;
}
if (c==2)
{
last=t/(mid*mid)+(t%(mid*mid)!=0);
b[add][0]-=1ll*last*(i+mid)*(i+mid);
b[add][1]+=1ll*2*(i+mid)*last;
b[add][2]-=last;
a[0]+=1ll*last*(i+mid)*(i+mid);
a[1]-=1ll*2*(i+mid)*last;
a[2]+=last;
}
ans+=last;
}
if (ans<=k) r=mid;else l=mid+1;
}
if (l==100000) printf("-1");else printf("%d",r);
return 0;
}
如果自己说什麽都做不到而什麽都不去做的话,那就更是什麽都做不到,什麽都不会改变,什麽都不会结束.