BZOJ2216: [Poi2011]Lightning Conductor
阿新 • • 發佈:2019-02-14
題目大意:已知一個長度為n的序列a1,a2,...,an。對於每個1<=i<=n,找到最小的非負整數p滿足 對於任意的j, aj < = ai + p - sqrt(abs(i-j))
額,不寫題解了,好像也不一定能寫出來
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define N 500010 using namespace std; int a[N]; struct ppp {int w,l,r;}p[N]; double cal(int x,int now) {return a[x]+sqrt(abs(now-x));} int ans1[N],ans2[N]; int main() { int n,i,j,x,y; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); int h=1,t=0; for(i=1;i<=n;i++) { p[h].l++; if(h<=t&&p[h].l>p[h].r) h++; while(t>=h&&cal(p[t].w,p[t].l)<=cal(i,p[t].l)) t--; if(h>t) { t++; p[t]=(ppp){i,i,n}; } else { int l=p[t].l,r=p[t].r+1; while(l<r) { int mid=(l+r)>>1; if(cal(p[t].w,mid)<=cal(i,mid)) r=mid; else l=mid+1; } p[t].r=l-1; t++; p[t]=(ppp){i,l,n}; } ans1[i]=max(ceil(cal(p[h].w,i))-a[i],0.0); } for(i=1;i<=n/2;i++) swap(a[i],a[n-i+1]); h=1,t=0; for(i=1;i<=n;i++) { p[h].l++; if(h<=t&&p[h].l>p[h].r) h++; if(h>t||cal(i,n)>cal(p[t].w,n)) { while(t>=h&&cal(p[t].w,p[t].l)<=cal(i,p[t].l)) t--; if(h>t) { t++; p[t]=(ppp){i,i,n}; } else { int l=p[t].l,r=p[t].r+1; while(l<r) { int mid=(l+r)>>1; if(cal(p[t].w,mid)<=cal(i,mid)) r=mid; else l=mid+1; } p[t].r=l-1; t++; p[t]=(ppp){i,l,n}; } } ans2[i]=max(ceil(cal(p[h].w,i))-a[i],0.0); } for(i=1;i<=n;i++) printf("%d\n",max(ans1[i],ans2[n-i+1])); }