1. 程式人生 > 實用技巧 >《演算法競賽進階指南》0x42樹狀陣列 樓蘭圖騰

《演算法競賽進階指南》0x42樹狀陣列 樓蘭圖騰

題目連結: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; }