Ping pong UVALive - 4329

题意:树状数组水题,要求对于输入的数据ai,有函数f(ai)为左侧小于ai的数乘右侧大于ai的数,反之亦然,之后求∑f(ai)。

思路:由于题目限制了ai最大为1e5,因此我们可以通过存在x[ai]时+1求sum(ai)为此时小于ai的数,同样的方法也可以求出另外三种数。

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define mem(x) (memset(x,0,sizeof(x)))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
int n,a[100005],c[100005];
int lowbit(int x)
{
    return x&-x;
}
int max_num;
ll sum(int x)
{
    ll ret=0;
    while(x>0)
    {
        ret+=c[x];x-=lowbit(x);
    }
    return ret;
}
void add(int x,int d)
{
   // cout<<x<<d;
    while(x<=max_num)
    {
        c[x]+=d;
        x+=lowbit(x);
    }
}
// head
 int main()
{
//ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int __;
    cin>>__;
    while(__--)
    {
        cin>>n;
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        vector<int>pre(n+1);
        int s;
        max_num=-1;
        rep(i,1,n+1)
        {
            cin>>a[i];
       //     cout<<s;
            max_num=max(max_num,a[i]);
        }
        ll ans=0;
        per(i,1,n+1)
        {
            pre[i]=sum(a[i]);
            add(a[i],1);
        }
        per(i,1,n+1)
        {
            ll ls=sum(a[i]-1);
            ans+=(n-i-pre[i])*(ls-pre[i])+(i-ls+pre[i]-1)*pre[i];
        }
        cout<<ans<<endl;
    }

}

 

posted @ 2021-03-05 15:44  大抵一个菜鸡而已  阅读(24)  评论(0编辑  收藏  举报