洛谷題目傳送門c++
這題推式子噁心。。。。。spa
考慮分治,每次統計跨過\(mid\)的全部區間的答案和。\(i\)從\(mid-1\)到\(l\)枚舉,統計以\(i\)爲左端點的全部區間。指針
咱們先維護好\([i,mid]\)區間內最小值\(mn\)和最大值\(mx\)。咱們能夠想到,對於某一個左端點,它的右端點\(j\)在必定的範圍內,最小值和最大值都不會變。這裏就看到一些能夠重複利用並快速計算的信息了。code
維護兩個指針\(p,q\),分別表示\([mid+1,r]\)內元素值第一個小於\(mn/\)大於\(mx\)的位置,那麼\(\sum\limits_{j=mid+1}^rans[i,j]\)就能夠分紅三類討論。暫時假設\(p<q\)。ip
\(j\in[mid+1,p-1]\)時,區間的最值不變,都是\(mn,mx\),直接高斯求和get
\[ans\leftarrow mn\cdot mx\sum\limits_{j=mid+1}^{p-1}j-i+1\]it
\(j\in[p,q-1]\)時,區間最大值不變,但最小值取的是\([mid+1,j]\)裏的了。預處理\(mid+1\)到\(r\)的前綴最小值\(min_j\),同時記錄\(min_j\)和\(min_j\cdot j\)的前綴和(\(p\ge q\)同理)class
\[ans\leftarrow mx\sum\limits_{j=p}^{q-1}min_j(j-i+1)\]變量
\[ans\leftarrow mx\sum\limits_{j=p}^{q-1}min_j\cdot j+mx(1-i)\sum\limits_{j=p}^{q-1}min_j\]im
\(j\in[q,r]\)時,最值和\(mn,mx\)無關了,記錄\(min_jmax_j\)和\(min_jmax_j\cdot j\)的前綴和
\[ans\leftarrow \sum\limits_{j=q}^rmin_jmax_j(j-i+1)\]
\[ans\leftarrow \sum\limits_{j=q}^rmin_jmax_j\cdot j+(1-i)\sum\limits_{j=q}^rmin_jmax_j\]
容易發現\(mn,mx,p,q\)都是單調移動的,那麼就大功告成啦!
#include<bits/stdc++.h> #define LL long long #define RG register #define R RG LL//常數大也無所謂了 #define G if(++ip==ie)fread(ip=buf,1,N,stdin) #define A(V) (ans+=V)%=YL using namespace std; const LL N=1<<19,YL=1e9; char buf[N],*ie=buf+N,*ip=ie-1; LL ans,a[N],mns[N],mxs[N],mnj[N],mxj[N],mms[N],mmj[N]; inline LL in(){ G;while(*ip<'-')G; R x=*ip&15;G; while(*ip>'-'){x*=10;x+=*ip&15;G;} return x; } inline LL S(R l,R r){//高斯求和 return (l+r)*(r-l+1)/2%YL; } void solve(R l,R r){ if(l==r){A(a[l]*a[l]);return;} R m=(l+r)>>1,i,j,p,q,mn=YL,mx=0; solve(l,m);solve(m+1,r); mns[m]=mxs[m]=mnj[m]=mxj[m]=mms[m]=mmj[m]=0; for(j=m+1;j<=r;++j){//預處理,變量名不解釋 mn=min(mn,a[j]);mx=max(mx,a[j]); mns[j]=(mns[j-1]+mn)%YL; mxs[j]=(mxs[j-1]+mx)%YL; mnj[j]=(mnj[j-1]+mn*j)%YL; mxj[j]=(mxj[j-1]+mx*j)%YL; mms[j]=(mms[j-1]+mn*mx)%YL; mmj[j]=(mmj[j-1]+mn*mx%YL*j)%YL; } mn=YL;mx=0; for(p=q=m+1,i=m;i>=l;--i){//計算答案 mn=min(mn,a[i]);mx=max(mx,a[i]); while(p<=r&&mn<a[p])++p;//單調移動 while(q<=r&&mx>a[q])++q; if(p<q){ A(mn*mx%YL*S(m-i+2,p-i));//注意作減法的都要加一下模數 A(mx*(mnj[q-1]-mnj[p-1]+YL)+mx*(mns[q-1]-mns[p-1]+YL)%YL*(1-i+YL)); A(mmj[r]-mmj[q-1]+(mms[r]-mms[q-1]+YL)*(1-i+YL)); } else{ A(mn*mx%YL*S(m-i+2,q-i)); A(mn*(mxj[p-1]-mxj[q-1]+YL)+mn*(mxs[p-1]-mxs[q-1]+YL)%YL*(1-i+YL)); A(mmj[r]-mmj[p-1]+(mms[r]-mms[p-1]+YL)*(1-i+YL)); } } } int main(){ R n=in(); for(R i=1;i<=n;++i)a[i]=in(); solve(1,n); printf("%lld\n",ans); return 0; }