codeforces 1167F Scalar Queries

思路
容易想到对于每个位置考虑包含这个位置的贡献
因为贡献中i代表的是一段区间中顺序第i位的
故可以考虑从小到大枚举
以下计算a[s]对ans的贡献

c o n t i b u t e s / a [ s ] = ∑ 1 < = j < = s ∑ s < = k < = n ( p r e k − p r e j − 1 + 1 ) = s ∗ ( n − s + 1 ) + s ∗ ∑ s < = k < = n p r e k − ( n − s + 1 ) ∗ ∑ 1 < = j < = s p r e j − 1 = s ∗ ( n − s + 1 ) + s ∗ ( p r e n ( 2 ) − p r e s − 1 ( 2 ) ) − ( n − s + 1 ) ∗ p r e s − 1 ( 2 ) contibute_s /a[s] = \sum_{1<=j<=s}\sum_{s<=k<=n} (pre_k - pre_{j-1}+1) \\ = s*(n-s+1)+s*\sum_{s<=k<=n}pre_k - (n-s+1)*\sum_{1<=j<=s}pre_{j-1} \\ =s*(n-s+1)+s*(pre^{(2)}_{n}-pre^{(2)}_{s-1})-(n-s+1)*pre^{(2)}_{s-1} contibutes/a[s]=1<=j<=ss<=k<=n(prekprej1+1)=s(ns+1)+ss<=k<=nprek(ns+1)1<=j<=sprej1=s(ns+1)+s(pren(2)pres1(2))(ns+1)pres1(2)

p r e k pre_k prek表示前k个数中小于a[s]的个数
p r e ( 2 ) pre^{(2)} pre(2)表示2阶前缀和
然后利用树状数组维护一下即可

因为没mod Wa了几发,还是太菜了

#include
using namespace std;
const int MAX_N =5e5 + 5;
int n;
typedef long long ll;
ll b1[MAX_N], b2[MAX_N], a[MAX_N],r[MAX_N];
pair p[MAX_N];
const ll mod = 1e9 + 7;

void add(int i, int x, ll* b) {
	for (; i <= n; i += i & -i) b[i] =(b[i]+ x)%mod;
}

ll sum(int i, ll* b) {
	ll res = 0;
	for (; i; i -= i & -i) res = res + b[i];
	return res%mod;
}
ll SUM(int i) {
	return i * sum(i, b2)%mod + sum(i, b1);
}
void ADD(int i) {
	add(i, 1, b2);
	add(i, -(i - 1), b1);
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i], p[i].first = a[i], p[i].second=i;
	sort(p + 1, p + 1 + n);
	for (int i = 1; i <= n; i++) r[p[i].second] = i;
	ll ans = 0;
	for (int i = 1; i <= n; i++) {
		ll s = p[i].second;
		ll append = (SUM(n) - SUM(s - 1))%mod*s%mod - SUM(s - 1)*(n - s + 1) % mod;
		ans = ((append+s*(n-s+1))%mod*a[s]+ans) % mod;
		ADD(s);
	}
	cout << (ans+mod)%mod << endl;
	//system("pause");
}

你可能感兴趣的:(ACM)