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; } }