b_hdu_Ping pong(树状数组+乘法原理)

有n个人要进行乒乓球比赛每一个人都一个能力值;现在要求进行一场1个裁判2个选手的比赛,不能选择技术等级高于或低于他们两人的裁判,裁判位置也需在两人的中间,问一共可以进行这种比赛多少次。(1<=ai<=100000, N<20000)
1
3 1 2 3
1

思路
树状数组+乘法原理

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll n, ans, a[N], c[N], lmin[N], rmax[N], lmax[N], rmin[N];
int lowbit(int x) {return x&-x;}
void add(int x, ll v) {
    for (; x<N; x+=lowbit(x)) c[x]+=v;
}
ll ask(int x) {
    ll ans=0;
    for (; x>0; x-=lowbit(x)) ans+=c[x];
    return ans;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t; cin>>t;
    while (t--) {
        memset(c,0,sizeof c);
        cin>>n; for (int i=1; i<=n; i++) cin>>a[i], lmin[i]=lmax[i]=rmin[i]=rmax[i]=0;
        for (int i=1; i<=n; i++) {
            ll l=ask(a[i]);
            lmin[i]=l, lmax[i]=i-l-1;
            add(a[i], 1);
        }
        memset(c,0,sizeof c);
        for (int i=n,j=1; i>0; i--,j++) {
            ll r=ask(a[i]); //右边比a[i].v小的数的个数
            rmin[i]=r, rmax[i]=j-r-1;
            add(a[i], 1);
        }
        // for (int i=1; i<=n; i++) cout<<lmin[i];
        // cout<<'\n';
        // for (int i=1; i<=n; i++) cout<<lmax[i];
        // cout<<'\n';
        // for (int i=1; i<=n; i++) cout<<rmin[i];
        // cout<<'\n';
        // for (int i=1; i<=n; i++) cout<<rmax[i];
        for (int i=1; i<=n; i++) ans+=lmin[i]*rmax[i]+lmax[i]*rmin[i];
        cout<<ans<<'\n';
    }
    return 0;
}
posted @ 2020-11-04 14:30  童年の波鞋  阅读(148)  评论(1编辑  收藏  举报