BZOJ5055: 膜*

n<=300000个数求所有i<j<k,Ai>Aj>Ak的Ai*Aj*Ak的和。

还以为什么奇怪题呢。。就是个偏序。。

i<j,Ai>Aj就是逆序对模板,把树状数组里的+1改成+Ai即可,每个数的Ai*Aj数就树状数组求个前缀和即可。

上面那个算出来存在Bi,再用类似的方法求一次即可。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #include<algorithm>
 5 //#include<queue>
 6 //#include<iostream>
 7 using namespace std;
 8 
 9 int n;
10 #define maxn 300011
11 const int mod=19260817;
12 int a[maxn],id[maxn],two[maxn],thr[maxn];
13 int lisan[maxn];
14 struct BIT
15 {
16     int a[maxn];
17     void clear() {memset(a,0,sizeof(a));}
18     void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]=(a[x]+v)%mod;}
19     int query(int x) {int ans=0;for (;x;x-=x&-x) ans=(ans+a[x])%mod;return ans;}
20 }t;
21 int main()
22 {
23     scanf("%d",&n);
24     for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisan[i]=a[i];
25     sort(lisan+1,lisan+1+n);
26     for (int i=1;i<=n;i++) id[i]=lower_bound(lisan+1,lisan+1+n,a[i])-lisan;
27     t.clear();
28     for (int i=1;i<=n;i++)
29     {
30         t.add(id[i],a[i]);
31         two[i]=1ll*a[i]*t.query(id[i]-1)%mod;
32     }
33     t.clear();
34     int ans=0;
35     for (int i=1;i<=n;i++)
36     {
37         t.add(id[i],two[i]);
38         ans=(ans+1ll*a[i]*t.query(id[i]-1)%mod)%mod;
39     }
40     printf("%d
",ans);
41     return 0;
42 }
View Code

跑得有点慢 难道被xu掉了?

原文地址:https://www.cnblogs.com/Blue233333/p/7603347.html