CF1167F Scalar Queries

题目描述

给你一个序列\(a_{1},a_{2}....a_{n}\)其中每个元素的值互不相同

定义函数\(f(l,r)\)

  • 定义数组\(b_{1},b_{2}...b_{r-l+1},\)其中\(b_{i}=a_{r-l+i}\)
  • \(b\)按从小到大排序
  • 此时的函数值是\(\sum \limits_{i=1}^{r-l+1}b_{i}*i\)

计算\(1<=l<=r<=n\)所有的\(f(l,r)\),模数\(1e9+7\)

如果按照题目中的意思暴力算的话最优也是\(O(n^2log(n))\),显然无法同过,那么我们把\(*i\)这部分转换一下

\(i\)也就是\(b_{i}\)在这个区间里面小于等于这个数的个数

那么\(a_{i}\)对答案造成的总贡献也就是在所有的区间里面小于等于这个数的个数总和(下文统称\(sum_{i}\))\(*a_{i}\)

然后\(sum_{i}\)可以用树状数组来求出来,就是正着扫一遍,倒着再扫一遍就好了,只不过第一遍要先插入再统计

后面那一遍要先统计再扫,复杂度\(O(nlog(n))\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int maxn=5e5+5;
const int mod=1e9+7;
int lsh[maxn],a[maxn],n,b[maxn],sum[maxn];
struct szsz{
	#define lowbit(x) (x&(-x))
	int c[maxn];
	inline void update(int x,int val)
	{for(;x<=n;x+=lowbit(x)){c[x]+=val;}}
	inline int query(int x)
	{int res=0;for(;x;x-=lowbit(x)){res+=c[x];}return res%mod;}
	inline void clear(){memset(c,0,sizeof(c));}
}tr;
signed main()
{
	n=read();
	for(int i=1;i<=n;i++) a[i]=lsh[i]=read();
	sort(lsh+1,lsh+1+n);
	for(int i=1;i<=n;i++)b[i]=lower_bound(lsh+1,lsh+1+n,a[i])-lsh;
	for(int i=1;i<=n;i++)
	{
		tr.update(b[i],i);
		sum[i]=tr.query(b[i])*(n-i+1)%mod;
	}	
	tr.clear();
	for(int i=n;i>=1;i--)
	{
		sum[i]=(sum[i]+tr.query(b[i])*i)%mod;
		tr.update(b[i],n-i+1);
	}
	int ans=0;
	for(int i=1;i<=n;i++) ans=(ans+a[i]*sum[i])%mod;
	printf("%lld\n",ans);
}
posted on 2021-11-03 21:41  JYFHYX  阅读(30)  评论(0编辑  收藏  举报