2020 CCPC-Wannafly Winter Camp Day7 ---A.序列

对于每个元素对(i,j),对于所有min((s_i),(s_j))<x<max((s_i),(s_j)),这个元素对的贡献都是(2^{n-(j-i+1)})
(2^{i-j})
我们考虑k+1的得分和,就是k的得分和减去一部分,再加上一部分。
减去的一部分只对k有贡献而对k+1没有贡献的,是(1,k+1),(2,k+1)...(k-1,k+1)这些值对应的位置对的贡献
加上的一部分只对k+1有贡献而对k没有贡献的,是(k,k+2),(k,k+3)..(k,n)这些值对应的位置对的贡献
于是我们求出所有(delta_k)=(ans_k)-(ans_{k-1})
1.我们从前往后扫描序列,对于当前位置我们考虑它作为位置对的右端点,即上述j。
那么我们认为这个点的贡献是(2^{n-j})
我们将这个点作为值对的右端点,即大的那一个,那我们求出j位置前面所有小于(s_j)的数作为位置对的左端点,贡献为(2^{i-1})。这会对(delta_{s_j})产生-(sum 2^{i-1})的贡献。
我们将这个点作为值对的左端点,即小的哪一个,那我们求处j位置前面所有大于(s_j)的数作为位置对的左端点,贡献为(2^{i-1})。这会对(delta_{s_{j+1}})产生(sum 2^{i-1})的贡献。
所有符合条件的(2^{i-1})的和我们用树状数组维护即可。
每次将计算完答案,将这个点作为左端点塞进树状数组。
2.我们再从后往前扫描序列,对于当前位置我们考虑作为位置对的左端点,及上述i。
做法同上。

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const ll mol = 1e9 +7;
const int maxn = 1e5;
int n;
int a[maxn + 11];
ll delta[maxn + 11],mul[maxn + 11],bit[maxn + 11];

ll sub(ll a,ll b) { a -= b; return a < 0 ? a + mol : a; }
ll add(ll a,ll b) { a += b; return a >= mol ? a - mol : a; }
int lowbit(int x) { return x & (-x); }
void upd(int x,ll val) { for (; x <= n; x += lowbit(x)) bit[x] = add(bit[x] , val); }
ll query(int x) { ll ans = 0; for (; x ; x -= lowbit(x)) ans = add(ans , bit[x]); return ans; }

int main(){
    scanf("%d" , &n);
    for (int i = 1; i <= n; i++) scanf("%d" , &a[i]);
    mul[0] = 1;
    for (int i = 1; i <= n; i++) mul[i] = mul[i - 1] * 2 % mol;
    for (int i = 1; i <= n; i++) {
        ll val = query(a[i] - 1) * mul[n - i] % mol;
        delta[a[i]] = sub(delta[a[i]] , val);
        val  = sub(query(n) , query(a[i])) * mul[n - i] % mol;
        delta[a[i] + 1] = add(delta[a[i] + 1] , val);
        upd(a[i] , mul[i - 1]);
    }
    for (int i = 1; i <= n; i++) bit[i] = 0;
    for (int i = n; i >= 1; i--) {
        ll val = sub(query(n) , query(a[i])) * mul[i - 1] % mol;
        delta[a[i] + 1] = add(delta[a[i] + 1] , val);
        val = query(a[i] - 1) * mul[i - 1] % mol;
        delta[a[i]] = sub(delta[a[i]] , val);
        upd(a[i] , mul[n - i]);
    }
    for (int i = 1; i <= n; i++) {
        delta[i] = add(delta[i] , delta[i - 1]);
        printf("%lld
" , delta[i]);
    }
}
原文地址:https://www.cnblogs.com/Embiid/p/12260295.html