bzoj3745: [Coci2015]Norma
我要哭了我终于A了,中午没保存然后重推柿子重写然后改一波LL就A了哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
这个题我诚实的说%了下题解:就是分治的时候,算左边(l~mid)到右边(mid+1~r)
枚举右界,仔细想想可以把区间分成3块分情况讨论。接下来就是艰苦卓绝的化柿子了
我写这种理性的题果然。。。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9; LL getsum(LL st,LL ed){return ((st+ed)*(ed-st+1)/2)%mod;}//等差数列求和 LL MOD(LL x){return (x%mod+mod)%mod;} LL a[510000],ans; struct Right { LL st,ed,rmn,rmx; Right(){} Right(LL ST,LL ED,LL RMN,LL RMX){st=ST,ed=ED,rmn=RMN;rmx=RMX;} }R[510000];int Rlen; LL g[510000],h[510000]; void cdq(LL l,LL r) { if(l==r){ans=(ans+a[l]*a[l])%mod;return ;} int mid=(l+r)/2; LL rmn=a[mid+1],rmx=a[mid+1]; Rlen=0; R[++Rlen]=Right(mid+1,mid+1,rmn,rmx); for(int i=mid+2;i<=r;i++) { if(rmn>a[i]||rmx<a[i]) { rmn=min(rmn,a[i]); rmx=max(rmx,a[i]); R[++Rlen]=Right(i,i,rmn,rmx); } else R[Rlen].ed++; } //--------------------分块---------------------- g[Rlen+1]=0;h[Rlen+1]=0; for(int i=Rlen;i>=1;i--) { g[i]= (g[i+1] + (getsum(R[i].st,R[i].ed)*(R[i].rmn*R[i].rmx%mod))%mod )%mod; h[i]= (h[i+1] + ((R[i].ed-R[i].st+1)*(R[i].rmn*R[i].rmx%mod))%mod )%mod; } //-----------------------右区间预处理函数g,h------------------------ LL j=0,k=0; int w=-1;LL Gmn=0,Hmn=0,Gmx=0,Hmx=0;//动态维护中部答案 LL lmn=(1LL<<62),lmx=0; for(LL i=mid;i>=l;i--) { lmn=min(lmn,a[i]); lmx=max(lmx,a[i]); while(j<Rlen&&(lmn<=R[j+1].rmn&&lmx>=R[j+1].rmx)) { j++; if(j<=k) { if(w==0) { Gmx=MOD( Gmx-(getsum(R[j].st,R[j].ed)*R[j].rmx%mod) ); Hmx=MOD( Hmx-((R[j].ed-R[j].st+1)*R[j].rmx%mod) ); } else { Gmn=MOD( Gmn-(getsum(R[j].st,R[j].ed)*R[j].rmn%mod) ); Hmn=MOD( Hmn-((R[j].ed-R[j].st+1)*R[j].rmn%mod) ); } } } while(k<Rlen&&(lmn<=R[k+1].rmn||lmx>=R[k+1].rmx)) { k++; if(lmn<=R[k].rmn&&lmx>=R[k].rmx) Gmn=0, Hmn=0, Gmx=0, Hmx=0; else { w=(lmn<=R[k].rmn)?0:1; if(w==0) { Gmx=( Gmx+(getsum(R[k].st,R[k].ed)*R[k].rmx%mod) )%mod; Hmx=( Hmx+((R[k].ed-R[k].st+1)*R[k].rmx%mod) )%mod; } else { Gmn=( Gmn+(getsum(R[k].st,R[k].ed)*R[k].rmn%mod) )%mod; Hmn=( Hmn+((R[k].ed-R[k].st+1)*R[k].rmn%mod) )%mod; } } } //-------------------extend&&单调维护中部------------------------- if(j>0&&j<=r)ans=( ans + ( MOD(getsum(mid+1,R[j].ed)-((R[j].ed-mid)*(i-1)%mod)) * ((lmn*lmx)%mod) %mod ) )%mod; //左区间 if(j+1<=k) { if(w==0)ans=( ans + lmn*MOD(Gmx-((i-1)*Hmx))%mod )%mod; else ans=( ans + lmx*MOD(Gmn-((i-1)*Hmn))%mod )%mod; } //中部 if(k+1<=r)ans=( ans + MOD( g[k+1]-((i-1)*h[k+1]%mod) ) )%mod; //右区间 } cdq(l,mid),cdq(mid+1,r); } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); ans=0;cdq(1,n); printf("%lld\n",ans); return 0; }
pain and happy in the cruel world.