Yoi #371 梯度彌散
阿新 • • 發佈:2020-11-22
題面
分析
考試時題目看錯白白耗了一個小時(tmd下次在看錯我就***)
顯然二分
二分之後可以通過差分的手段\(O(n)\)判斷是否可行
- \(1=1+0\)
- \(x=(x+1)-1\)
- \(x^2=(x+1)^2-2x-1\)
用陣列維護即可
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e6+5; int n,C,K; ll a[N],f[N],g[N],h[N]; inline bool check(int x) { int ret=0; if(C==0) { for(int i=1;i<=n;i++) { f[i]=0; } for(int i=1;i<=n;i++) { f[i]+=f[i-1]; if(f[i]<a[i]) { ll t=a[i]-f[i]; f[i]+=t; f[i+x+1]-=t; ret+=t; if(ret>K) return 0; } } return 1; } else if(C==1) { for(int i=1;i<=n;i++) { f[i]=g[i]=0; } for(int i=1;i<=n;i++) { f[i]+=f[i-1]; g[i]+=g[i-1]-f[i]; if(g[i]<a[i]) { ll t=(a[i]-g[i]-1)/x+1; f[i]+=t; g[i]+=t*x; f[i+x+1]-=t; ret+=t; if(ret>K) return 0; } } } else { for(int i=1;i<=n;i++) { f[i]=g[i]=h[i]=0; } for(int i=1;i<=n;i++) { f[i]+=f[i-1]; g[i]+=g[i-1]-f[i]; h[i]+=h[i-1]-2*g[i]-f[i]; if(h[i]<a[i]){ ll t=(a[i]-h[i]-1)/(x*x)+1; f[i]+=t; g[i]+=t*x; h[i]+=t*x*x; f[i+x+1]-=t; ret+=t; if(ret>K) return 0; } } } return ret<=K; } int main() { freopen("dispersion.in","r",stdin); freopen("dispersion.out","w",stdout); int Num; scanf("%d%d%d%d",&Num,&n,&C,&K); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); int l=0,r=1e6,ans=-1; while(l<=r) { int mid=l+r>>1; if(check(mid)) ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); return 0; }