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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

序列问题

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

Description

Input
輸入文件名為seq.in。
首先輸入n。
接下來輸入n個數,描述序列 A。

Output
輸出文件名為seq.out。
輸出一行一個整數代表答案。

Sample Input
7
0 35 40 45 56 65 94

Sample Output
66636

Data Constraint
對于30%的數據,n<=5000
對于60%的數據,n<=50000
對于100%的數據,n<=500000,0<=A[i]<=10^9

.
.
.
.
.
分析
這題竟然用很神奇的分治?!

對于區間[x…y],將它分成三部分:
m = (x +y)/2
1.左右端點都在[x…m]里的。
2.左右端點都在[m + 1…y]里的。
3.左右端點在m的兩旁。

前兩個遞歸處理,考慮第三個怎么求,這是分治的常規套路。

先考慮區間[m + 1…y](右區間),以m+1為左端點,從左往右枚舉右端點,min值會不斷變小,max值會不斷變大,將變化的地方存下來,分別放進兩個數組里,設為a,b。

現在還要考慮區間[x…m](左區間),從m出發,從右往左枚舉左端點l,記錄下min值和max值,設為min_l,max_l。

最后需要將兩個區間合并。

在a數組里找到代表的值第一個小于min_l的位置u(從左往右看),
在b數組里找到代表的值第一個大于max_l的位置v(從左往右看)。
這個可以二分。
由于min_l不斷縮小,max_r不斷變大,也可以直接維護個指針。

右端點r的取法接下來有四種情況:

1.r < min(u, v),min_[l…r] = min_l, min_[l…r] = min_r。

2.r >= max(u, v), min_[l…r] = [l…r]里的點到m+1的最小值,max_[l…r] = [l…r]里的點到m+1的最大值。

3…u <= v, u<=r < v,min_[l…r] = [l…r]里的點到m+1的最小值,max_[l…r] = min_r。

4.u >v, v<=r < u,min_[l…r] = min_l,max_[l…r] = [l…r]里的點到m+1的最大值。

1可以直接算。2、3、4維護前綴和就行了。

.
.
.
.

程序:

#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std;long long mo=1000000007; long long ans=0; long long n,a[500005],u[500005],v[500005],s1[500005],s2[500005],s3[500005];void fz(long long x,long long y) {if (x>y) return;if (x==y){ans=(ans+a[x]*a[x]%mo)%mo; return;}long long mid=(x+y)/2;fz(x,mid); fz(mid+1,y);long long uu=1,vv=1;u[1]=v[1]=mid+1;s1[mid]=s2[mid]=s3[mid]=0;s1[mid+1]=s2[mid+1]=a[mid+1];s3[mid+1]=a[mid+1]*a[mid+1];for (int i=mid+2;i<=y;i++){if (a[i]<a[u[uu]]) u[++uu]=i;if (a[i]>a[v[vv]]) v[++vv]=i;s1[i]=(s1[i-1]+a[u[uu]])%mo;s2[i]=(s2[i-1]+a[v[vv]])%mo;s3[i]=(s3[i-1]+a[u[uu]]*a[v[vv]])%mo;}long long minn=2147483647,maxx=-2147483647,l=1,r=1;long long sum=ans;for (int i=mid;i>=x;i--) {minn=min(minn,a[i]);maxx=max(maxx,a[i]);while (l<=uu&&minn<=a[u[l]]) l++;while (r<=vv&&maxx>=a[v[r]]) r++;long long l1,r1;if (l>uu) l1=y; else l1=u[l]-1;if (r>vv) r1=y; else r1=v[r]-1;if (min(l1,r1)>mid) ans+=(long long)(min(l1, r1)-mid)*minn%mo*maxx%mo;if (max(l1,r1)<y) ans+=s3[y]-s3[max(l1,r1)];if (l1<=r1) ans+=(long long)(s1[r1]-s1[l1])*maxx%mo; else ans+=(long long)minn*(s2[l1]-s2[r1])%mo;ans=(ans%mo+mo)%mo;} } int main() {freopen("seq.in","r",stdin);freopen("seq.out","w",stdout);scanf("%lld",&n);for (int i=1;i<=n;i++) scanf("%lld",&a[i]);fz(1,n);printf("%lld",ans);fclose(stdin);fclose(stdout);return 0; }

轉載于:https://www.cnblogs.com/YYC-0304/p/10458938.html

總結

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

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