19_05_21校内训练[简单序列]
Posted greenduck
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19_05_21校内训练[简单序列]相关的知识,希望对你有一定的参考价值。
题意
定义一个序列的价值为其排序后所有位置(从1开始)乘以该位置元素的值的和,即∑i*ai。求一个长度为n的序列的所有连续子序列的价值和。
思考
一个序列的价值可看做所有的元素的和,加上所有无序二元组中较大的元素的值。
因此答案分为两部分:
1.所有可能序列的元素和的和。考虑一个点,算出有多少区间包含它既可。
2.无序二元组较大的元素的值。不难得出两个点之间的贡献是线性的,因此用树状数组维护所有小于等于某个数的位置和既可。正反各做一遍。
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const ll maxn=2E5+5; 5 const ll mod=1E9+7; 6 ll n,a[maxn],ans,m,tim[maxn]; 7 struct BIT 8 { 9 ll t[maxn]; 10 int lowbit(int x) 11 { 12 return x&-x; 13 } 14 void add(int x,ll y) 15 { 16 while(x<=m) 17 { 18 t[x]=(t[x]+y)%mod; 19 x+=lowbit(x); 20 } 21 } 22 ll ask(int x) 23 { 24 if(x==0) 25 return 0; 26 ll sum=0; 27 while(x) 28 { 29 sum=(sum+t[x])%mod; 30 x-=lowbit(x); 31 } 32 return sum; 33 } 34 void clear() 35 { 36 for(int i=1;i<=m;++i) 37 t[i]=0; 38 } 39 }T; 40 void get(int g) 41 { 42 for(int i=1;i<=n;++i) 43 { 44 ans=(ans+a[i]*T.ask(a[i]-g)%mod*(n-i+1))%mod; 45 T.add(a[i],i); 46 } 47 } 48 int main() 49 { 50 ios::sync_with_stdio(false); 51 cin>>n; 52 for(int i=1;i<=n;++i) 53 { 54 cin>>a[i]; 55 m=max(m,a[i]); 56 } 57 for(int i=1;i<=n;++i) 58 ans=(ans+a[i]*((n-i+1)+i+(n-i)*(i-1)%mod-1))%mod; 59 get(1); 60 T.clear(); 61 reverse(a+1,a+n+1); 62 get(0); 63 cout<<ans<<endl; 64 return 0; 65 }
以上是关于19_05_21校内训练[简单序列]的主要内容,如果未能解决你的问题,请参考以下文章