《演算法競賽進階指南》0x42樹狀陣列 樓蘭圖騰
阿新 • • 發佈:2020-07-13
題目連結:https://www.acwing.com/problem/content/243/
給定一個全排列,對於每個位置,都求前面有多少個數比它小,有多少個數比他大,右邊有多少個數比他小有多少個數比他大。通過樹狀陣列可以在O(nlogMAX)時間內求出。
程式碼:
#include<iostream> #include<cstdio> #include<string.h> using namespace std; const int maxn = 200010; int c[maxn]; int a[maxn]; int lmin[maxn],lmax[maxn],rmin[maxn],rmax[maxn];int lowbit(int x){return x&(-x);} int query(int x){ int ans=0; while(x){ ans+=c[x]; x-=lowbit(x); } return ans; } void update(int x,int C){ while(x<maxn){ c[x]+=C; x+=lowbit(x); } } int main(){ int n; cin>>n; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++){ lmin[i]=query(a[i]-1); lmax[i]=i-1-lmin[i]; update(a[i],1); } memset(c,0,sizeof(c)); for(int i=n;i;i--){ rmin[i]=query(a[i]-1); rmax[i]=n-i-rmin[i]; update(a[i],1); }long long ans1=0,ans2=0; for(int i=2;i<=n-1;i++){ ans2+=(long long)lmin[i]*rmin[i]; ans1+=(long long)lmax[i]*rmax[i]; } cout<<ans1<<" "<<ans2<<endl; }