日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jzoj5231-序列问题【分治】

發布時間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj5231-序列问题【分治】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


題目大意

nnn個數字,求
(∑l=1n∑r=lnmin{ai}?max{ai}(i∈[l..r]))%(109+7)(\sum_{l=1}^n\sum_{r=l}^nmin\{a_i\}*max\{a_i\}(i\in [l..r]))\%(10^9+7)(l=1n?r=ln?min{ai?}?max{ai?}(i[l..r]))%(109+7)


解題思路

考慮分治,單獨在半個內的分治下去計算,考慮如何計算跨過中點的區間。

有兩種情況:

  • minsminsminsmaxsmaxsmaxs全部在一邊。
    這時我們可以枚舉一邊的指針,然后因為minsminsminsmaxsmaxsmaxs都滿足單調性,所以另一半邊滿足的區間范圍也滿足單調性,之間指針掃過去
  • minsminsminsmaxsmaxsmaxs在不同邊
    枚舉右邊指針,然后兩個指針在左邊表示滿足的區間的范圍限制。之后用前綴和優化計算
  • 時間復雜度O(nlogn)O(n\ log\ n)O(n?log?n)


    codecodecode

    #include<cstdio> #include<algorithm> #define N 500010 #define ll long long using namespace std; const ll XJQ=1e9+7; ll ans,n,m; ll mi[N],mx[N],a[N],sum[N]; void dg(ll l,ll r) {ll j,k;if(l==r){(ans+=a[l]*a[l]%XJQ)%=XJQ;return;}if(l>r) return;ll mid=(l+r)/2;mi[mid+1]=mx[mid+1]=a[mid+1];mi[mid]=mx[mid]=a[mid];for(ll i=mid+2;i<=r;i++)mi[i]=min(a[i],mi[i-1]),mx[i]=max(a[i],mx[i-1]);for(ll i=mid-1;i>=l;i--)mi[i]=min(a[i],mi[i+1]),mx[i]=max(a[i],mx[i+1]);j=mid;for(ll i=mid+1;i<=r;i++){while(mi[j]>=mi[i]&&mx[j]<=mx[i]&&j>=l) j--;ans=(ans+mi[i]*mx[i]%XJQ*(mid-j)%XJQ)%XJQ;}j=mid+1;for(ll i=mid;i>=l;i--){while(mi[j]>=mi[i]&&mx[j]<=mx[i]&&!(mi[j]==mi[i]&&mx[j]==mx[i])&&j<=r) j++;ans=(ans+mi[i]*mx[i]%XJQ*(j-mid-1)%XJQ)%XJQ;}sum[l-1]=0;for(ll i=l;i<=mid;i++)sum[i]=sum[i-1]+mi[i];j=mid;k=mid;for(ll i=mid+1;i<=r;i++){while(mx[j]<mx[i]&&j>=l) j--;while(mi[k]>=mi[i]&&k>=l) k--;if(j+1<=k) ans=(ans+(sum[k]-sum[j])%XJQ*mx[i]%XJQ)%XJQ;}for(ll i=l;i<=mid;i++)sum[i]=sum[i-1]+mx[i];j=mid;k=mid;for(ll i=mid+1;i<=r;i++){while(mx[j]<=mx[i]&&j>=l) j--;while(mi[k]>mi[i]&&k>=l) k--;if(k+1<=j) ans=(ans+(sum[j]-sum[k])%XJQ*mi[i]%XJQ)%XJQ;}dg(l,mid);dg(mid+1,r); } int main() {freopen("seq.in","r",stdin);freopen("seq.out","w",stdout);scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);dg(1,n);printf("%lld",ans); }

    總結

    以上是生活随笔為你收集整理的jzoj5231-序列问题【分治】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。