[BZOJ5055]膜法师

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ5055]膜法师相关的知识,希望对你有一定的参考价值。

5055: 膜法师

Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 200  Solved: 102 [Submit][Status][Discuss]

Description

在经历过1e9次大型战争后的宇宙中现在还剩下n个完美维度,
现在来自多元宇宙的膜法师,想偷取其中的三个维度为伟大的长者续秒,
显然,他能为长者所续的时间,为这三个维度上能量的乘积,
但目前的宇宙很不乐观,胡乱偷取可能造成维度的崩溃,
所以,他必须按逆序偷取这些维度,且在偷取中,
每次偷取的维度的能量必须严格小于他上次偷取的能量,
由于膜法师生活在多元宇宙,所以他可以让所有可能的偷取方案全部发生
题目描述
但他数学不好,所以找到了你帮他求出能为长者续几秒,
你要做的,就是在给定的维度序列a中,
求出所有满足i<j<k且ai<aj<ak的ai*aj*ak的和
即 ∑ (a_i*a_j*a_k),要求  i<j<k  且 a_i<a_j<a_k
 

 

Input

第一行1个数 n
第二行n个数 a_i
 

 

Output

一个数,表示能为长者续几秒,由于长者是不朽的,
所以能活很久,不妨将答案对**19260817**取模吧
 

 

Sample Input

样例1
4
1 2 3 4

样例二
10
6 8 4 1 3 0 7 5 9 2

Sample Output

样例输出1
50
样例输出2
1737
样例解释
对于样例 1
有满足条件的序列为
{1,2,3}——6
{1,2,4}——8
{1,3,4}——12
{2,3,4}——24
ans=6+8+12+24=50
数据范围
30%的数据n<=300
60%的数据n<=3000
100%的数据n<=300000
0<=a[i]<=2147483647
 
先离散化再树状数组维护一下即可
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 300000 + 10;
const ll mod = 19260817;
int n, a[maxn];
int ref[maxn], num[maxn], num_cnt;
ll c1[maxn] = {0}, c2[maxn] = {0};
inline void Update(ll *arr, int pos, int val){
    for(int i = pos; i <= n; i += i & -i) arr[i] = (arr[i] + val) % mod;
}
inline ll Query(ll *arr, int pos){
    ll s = 0;
    for(int i = pos; i; i -= i & -i) s = (s + arr[i]) % mod;
    return s;
}
ll f[maxn], g[maxn];
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d", a + i);
        num[i] = a[i];
    }
    sort(num + 1, num + n + 1);
    num_cnt = unique(num + 1, num + n + 1) - (num + 1);
    for(int t, i = 1; i <= n; i++){
        t = lower_bound(num + 1, num + num_cnt + 1, a[i]) - num;
        ref[t] = a[i] % mod;
        a[i] = t;
    }
    for(int i = 1; i <= n; i++){
        f[i] = Query(c1, a[i] - 1);
        Update(c1, a[i], ref[a[i]]);
    }
    for(int i = n; i; i--){
        g[i] = Query(c2, n) - Query(c2, a[i]);
        if(g[i] < 0) g[i] += mod;
        Update(c2, a[i], ref[a[i]]);
    }
    ll ans = 0;
    for(int i = 1; i <= n; i++)
        ans = (ans + f[i] * g[i] % mod * ref[a[i]]) % mod;
    printf("%lld\n", ans);
    return 0;
}

 

以上是关于[BZOJ5055]膜法师的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ_5055_膜法师_树状数组+离散化

bzoj5055 膜法师

[BZOJ 5055]膜法师

bzoj5055 膜法师

bzoj 5055: 膜法师——树桩数组

bzoj5055膜法师(离散化+树状数组)