HDU 2492 Ping pong【树状数组好题! + 思维】

传送门
// 题意: 由西向东的给定n个人的rank值, 可以相同, 然后一场比赛的举行必须是裁判的rank值和它的位置都处于要进行比赛的两个人之间, 问最多可以举行多少场比赛.

// 思路: 很明显, 我们直接枚举中间位置的裁判, 所以我们需要维护几个东西就是每一个人它左边比它小的和比它大的, 右边比它小的和右边比它大的, 然后扫一遍即可出ans, 维护上面四个东西就是可以用两颗树状数组维护下就行啦~~~.

AC Code

const int maxn = 1e5+5;
int c1[maxn], c2[maxn];
void add1(int x) { for(;xvoid add2(int x) { for(;xint getsum1(int x){ int res=0; for(;x;x-=x&-x) res += c1[x]; return res;}
int getsum2(int x){ int res=0; for(;x;x-=x&-x) res += c2[x]; return res;}
int lmi[maxn], lmx[maxn], rmi[maxn], rmx[maxn], a[maxn];
void solve()
{
    int n; cin >> n ;
    Fill(c1, 0); Fill(c2, 0);
    for (int i = 1 ; i <= n ; i ++){
        cin >> a[i];
    }
    for (int i = 1 ; i <= n; i ++ ) {
        lmi[i] = getsum1(a[i]);
        lmx[i] = getsum1(maxn-1) - getsum1(a[i]);
        add1(a[i]);
    }
    for (int i = n ; i >= 1 ; i --) {
        rmi[i] = getsum2(a[i]);
        rmx[i] = getsum2(maxn-1) - getsum2(a[i]);
        add2(a[i]);
    }
    ll ans = 0;
    for (int i = 2 ; i < n ; i ++) {
        ans += lmi[i]*rmx[i] + lmx[i]*rmi[i];
    }
    cout << ans << endl;
}

你可能感兴趣的:(树状数组)