CF1167F Scalar Queries

题意

CF1167F Scalar Queries_第1张图片

题解

对于[l,r]中的一个数,不论[l,r]有多大,只有比它小的数可以影响到它的排名,那么就可以把ai从小到大排序,一个一个加入线段树中,线段树中下表为 i 的是ai(原来的位置,不是排序后的)分别为最右端和最左端时的排名总和(设为suml[i]、sumr[i]),ai的总贡献就是 ai * (suml[i-1] * (n-i+1) + sumr[i] * i)

当循环到一个点 i 时,他左边的任意一个点 j 会为 l <= j 且 r >= i 的区间中 i 的排名贡献1,右边的任意一个点 k 会为 l <= i 且 r >= k 的区间中 i 的排名贡献1,他自己也有贡献

所以加入一个点 i 时,就要把 i~n 的 suml 都加上 i ,把 1~i 的 sumr 都加上 n-i+1。

CODE

#include
#include
#include
#include
#include
#include
#include
#include
#define MAXN 500005
#define MAXM 1000005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x)&(x))
//#define int LL
//#pragma GCC optimize(2)
using namespace std;
inline LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 + (s - '0');s = getchar();}
	return x * f;
}
const int jzm = 1000000007;
int n,m,i,j,s,o,k;
struct it{
	int nm,id;
}a[MAXN];
bool cmp(it a,it b) {return a.nm < b.nm;}
int cl[MAXN],cr[MAXN];
void addt(int *c,int x,int y) {
	while(x <= n) {
		c[x] = (c[x] +0ll+jzm + y) % jzm;
		x += lowbit(x);
	}return ;
}
int sum(int *c,int x) {
	int as = 0;
	while(x > 0) {
		as = (as +0ll+jzm + c[x]) % jzm;
		x -= lowbit(x);
	}
	return as;
}
int main() {
	n = read();
	for(int i = 1;i <= n;i ++) {
		a[i].nm = read();a[i].id = i;
	}
	sort(a + 1,a + 1 + n,cmp);
	int ans = 0;
	for(int i = 1;i <= n;i ++) {
		addt(cl,a[i].id,a[i].id);
		addt(cr,1,n - a[i].id + 1);
		addt(cr,a[i].id+1,a[i].id - n - 1);
		ans = (ans +0ll+jzm +(sum(cl,a[i].id-1) *1ll* (n - a[i].id + 1) % jzm +0ll+ sum(cr,a[i].id) *1ll* a[i].id % jzm) % jzm *1ll* a[i].nm % jzm) % jzm;
//		printf("ans: %d\n",ans);
	}
	printf("%d\n",ans);
	return 0;
}

 

你可能感兴趣的:(线段树)