一眼望去不會。
考慮問題中的\(f(i,j)=|\sum_{p=i}^{j}a_p |\)的實際意義。
其實就是前綴和相減的絕對值。
\(f(i,j)=|\ sum[j]-sum[i-1]\ |\)
\(f(i,j)=max(sum[j]-sum[i-1],sum[i-1]-sum[j])\)
那加上x呢。
\(f(i,j)=max[(sum[j]+xj)-(sum[i-1]+x(i-1)),(sum[i-1]+x(i-1))-(sum[j]+xj)]\)
\(sum[i]+xi\)聯想到直線。
咱們把這些直線放到座標系裏。
(這個圖是從別人那裏蒯過來的)
這是把樣例轉爲座標系中直線的效果圖。
對於一個 \(x\) ,咱們詢問的實際上就是橫座標爲x的兩條直線縱座標的差的最大值。
因此咱們用半平面交的方法維護出上下兩個凸包。
由於題目中的強制在線是假的(實際上處理出的\(x\in [-2n,2n]\))。
又由於凸包上的線段斜率是單調的,咱們能夠直接處理出全部 \(x\) 時的答案。
而後這題就解決了。node
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> #include<map> using namespace std; const int N=201000; const double eps=1e-8; double sum[N]; struct node{ double x,y; node(double xx=0,double yy=0){ x=xx;y=yy; } }; int top1,top2; struct Line{ node u,v; double w; }a[N],stack1[N],stack2[N]; node operator +(node a,node b){ return node(a.x+b.x,a.y+b.y); } node operator -(node a,node b){ return node(a.x-b.x,a.y-b.y); } node operator *(node a,double b){ return node(a.x*b,a.y*b); } double chaji(node a,node b){ return a.x*b.y-a.y*b.x; } node jiao(Line a,Line b){ double A=chaji(b.u-a.u,b.v-a.u); double B=chaji(b.v-a.v,b.u-a.v); return a.u+(a.v-a.u)*(A/(A+B)); } bool judge1(Line a,Line b,Line c){ node x=jiao(b,c); if(chaji(x-a.u,a.v-a.u)+eps>=0)return true; else return false; } bool judge2(Line a,Line b,Line c){ node x=jiao(b,c); if(chaji(x-a.u,a.v-a.u)+eps<0)return true; else return false; } int read(){ int sum=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();} return sum*f; } int n,m; double w(Line a,double x){ // cout<<a.w<<endl; return a.u.y+a.w*(x-(-2.0*n)); } map<int,double>ans; long long lastans; int main(){ n=read();m=read(); for(int i=1;i<=n;i++)sum[i]=sum[i-1]+read(); for(int i=1;i<=n;i++){ a[i].u=node(-2.0*n,sum[i]+i*-2.0*n); a[i].v=node(2.0*n,sum[i]+i*2.0*n); a[i].w=i; } a[0].u=node(-2.0*n,0);a[0].v=node(2.0*n,0); a[0].w=0; for(int i=0;i<=n;i++){ while(top1>1&&judge1(a[i],stack1[top1-1],stack1[top1]))top1--; stack1[++top1]=a[i]; } for(int i=n;i>=0;i--){ while(top2>1&&judge2(a[i],stack2[top2-1],stack2[top2]))top2--; stack2[++top2]=a[i]; } int now1=1;int now2=1; for(int i=-2*n;i<=n*2;i++){ while(now1<top1&&w(stack1[now1+1],i)>=w(stack1[now1],i))now1++; while(now2<top2&&w(stack2[now2+1],i)<=w(stack2[now2],i))now2++; double A=w(stack1[now1],i); double B=w(stack2[now2],i); ans[i]=A-B; } lastans=0; while(m--){ int x=read(); x=(x+lastans)%(4*n+1)-2*n; lastans=ans[x]; printf("%.0lf\n",ans[x]); } return 0; }