51Nod1680 区间求和

该博客探讨了一种区间求和问题,即求解区间内前k大元素的和。通过数学变形,将问题转化为求特定条件下的数对贡献,并提出了利用排序和树状数组的方法来解决这个问题。博主给出了代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

.
题目点这里
大概是这么一个问题
∑ k = 1 n ∑ i = 1 n − k + 1 ∑ j = i + k − 1 n 区 间 前 k 大 元 素 和 \sum_{k=1}^n\sum_{i=1}^{n-k+1}\sum_{j=i+k-1}^n区间前k大元素和 k=1ni=1nk+1j=i+k1nk
观察式子并加以变形
= ∑ i = 1 n ∑ j = i n ∑ k = 1 j − i + 1 区 间 前 k 大 元 素 和 =\sum_{i=1}^n\sum_{j=i}^n\sum_{k=1}^{j-i+1}区间前k大元素和 =i=1nj=ink=1ji+1k
= ∑ i = 1 n ∑ j = i n ∑ k = i j a [ k ] ∗ ∑ l = i j [ a [ l ] ≤ a [ k ] ] =\sum_{i=1}^n\sum_{j=i}^n\sum_{k=i}^ja[k]*\sum_{l=i}^j[a[l]\le a[k]] =i=1nj=ink=ija[k]l=ij[a[l]a[k]]
= ∑ i = 1 n ∑ j = i n ∑ k = i j a [ k ] ∗ ( 1 + ∑ l = i j [ a [ l ] &lt; a [ k ] ] ) =\sum_{i=1}^n\sum_{j=i}^n\sum_{k=i}^ja[k]*(1+\sum_{l=i}^j[a[l]&lt;a[k]]) =i=1nj=ink=ija[k](1+l=ij[a[l]<a[k]])
到了这里我们需要稍微考虑一下式子的意义
对于一对 i , j ( i &lt; j ) i,j(i&lt;j) i,j(i<j)假如有 a [ i ] &gt; a [ j ] a[i]&gt;a[j] a[i]>a[j]那么这一对 i , j i,j i,j对答案的贡献是多少
应该是 a [ i ] ∗ i ∗ ( n − j + 1 ) a[i]*i*(n-j+1) a[i]i(nj+1) [ i , j ] [i,j] [i,j]这个区间被 a [ i ] ∗ i ∗ ( n − j + 1 ) a[i]*i*(n-j+1) a[i]i(nj+1)个区间所包含)
同理如果 a [ j ] &gt; a [ i ] a[j]&gt;a[i] a[j]>a[i]那么贡献就是 a [ j ] ∗ i ∗ ( n − j + 1 ) a[j]*i*(n-j+1) a[j]i(nj+1)
算上原来式子里有一个 1 1 1就得到下面这样的式子
= ∑ i = 1 n ( a [ i ] ∗ i ∗ ( n − i + 1 ) + =\sum_{i=1}^n(a[i]*i*(n-i+1)+ =i=1n(a[i]i(ni+1)+ ∑ j = i n i ∗ ( n − j + 1 ) ∗ ( a [ i ] ∗ [ a [ i ] &lt; a [ j ] ] + a [ j ] ∗ [ a [ j ] &gt; a [ i ] ] ) ) \sum_{j=i}^n i*(n-j+1)*(a[i]*[a[i]&lt;a[j]]+a[j]*[a[j]&gt;a[i]])) j=ini(nj+1)(a[i][a[i]<a[j]]+a[j][a[j]>a[i]]))
把他拆成三个部分就是
∑ i = 1 n ( a [ i ] ∗ i ∗ ( n − i + 1 ) \sum_{i=1}^n(a[i]*i*(n-i+1) i=1n(a[i]i(ni+1)
∑ i = 1 n ∑ j = i n i ∗ ( n − j + 1 ) ∗ a [ j ] ∗ [ a [ j ] &gt; a [ i ] ] \sum_{i=1}^n\sum_{j=i}^n i*(n-j+1)*a[j]*[a[j]&gt;a[i]] i=1nj=ini(nj+1)a[j][a[j]>a[i]]
∑ i = 1 n ∑ j = i n i ∗ ( n − j + 1 ) ∗ a [ i ] ∗ [ a [ j ] &lt; a [ i ] ] \sum_{i=1}^n\sum_{j=i}^n i*(n-j+1)*a[i]*[a[j]&lt;a[i]] i=1nj=ini(nj+1)a[i][a[j]<a[i]]
第一个不用求
第二个可以这样变形
∑ j = 1 n ( n − j + 1 ) ∗ a [ j ] ∑ i = 1 j i ∗ [ a [ j ] &gt; a [ i ] ] \sum_{j=1}^n(n-j+1)*a[j]\sum_{i=1}^j i*[a[j]&gt;a[i]] j=1n(nj+1)a[j]i=1ji[a[j]>a[i]]
可以用排序+树状数组解决
第三个一样的
贴个 c o d e code code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1000010
#define LL long long
#define M 1000000007
using namespace std;
int n,s[N],B,C,r[N]; LL A=0;
struct fenwick{
	LL w[N],S;
	inline void clr(){ memset(w,0,sizeof w); }
	inline void add(int x,int k){ for(;x<=n;x+=x&-x) w[x]+=k; }
	inline LL sum(int x){ for(S=0;x;x&=x-1) S=(S+w[x])%M; return S; }
} w;
inline bool c1(int i,int j){ return s[i]<s[j]; }
int main(){
	scanf("%d%d%lld%d%d",&n,s+1,&A,&B,&C); r[1]=1;
	for(int i=2;i<=n;++i) s[r[i]=i]=((LL)s[i-1]*A+B)%C;
	sort(r+1,r+1+n,c1); A=0;	
	for(int i=1,j;i<=n;++i){
		j=r[i];
		A=(A+w.sum(j)*s[j]%M*(n-j+1)%M)%M;
		w.add(j,j);
	}
	w.clr();
	for(int i,j=1;j<=n;++j){
		i=r[j];
		A=(A+(w.sum(n)-w.sum(i))*s[i]%M*i%M)%M;
		w.add(i,n-i+1);
	}
	for(int i=1;i<=n;++i) A=(A+(LL)s[i]*i%M*(n-i+1)%M)%M;
	printf("%lld\n",A);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值