『Luogu 1637』三元上升子序列 (樹狀數組)
阿新 • • 發佈:2018-09-26
algo gis name long long stream namespace spa href 樹狀
題目鏈接
題目描述
Erwin最近對一種叫"thair"的東西巨感興趣。。。
在含有\(n\)個整數的序列\(a_1,a_2 \dots a_n\)中,
三個數被稱作"thair"當且僅當\(i<j<k\)且\(a_i<a_j<a_k\)
求一個序列中"thair"的個數。
解題思路
典型的偏序問題,我們固定\(j\)的位置,問題就變成了在\(j\)前面有多少個數比\(a_j\)小,在\(j\)後面有多少數比\(a_j\)大,答案顯然就是兩個的乘積。
顯然,可以用主席樹做
當然,我是來練習樹狀數組的【霧】,所以就拿樹狀數組寫吧。。。。
首先,我們從後向前掃一遍,可以得到比當前大的有多少個(借助桶排序的思路)。
同理,我們從前向後掃一遍,可以得到比當前小的有多少個。
然後統計答案就OK了。
辣雞lower_bound WA了十幾次嗚嗚嗚嗚o(TヘTo)
代碼
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define ll long long using namespace std; const ll maxn=40050; ll n,len; ll a[maxn],b[maxn],aa[maxn]; ll shun[maxn],ni[maxn]; ll num[maxn<<2]; inline ll lowbit(ll x){return x&(-x);} inline ll query(ll x){ ll ans=0; while(x>0){ ans+=num[x]; x-=lowbit(x); } return ans; } inline void add(ll x){ while(x<(maxn<<2)){ num[x]++; x+=lowbit(x); } } int main(){ scanf("%lld",&n); for(register int i=1;i<=n;i++)scanf("%lld",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); len=unique(b+1,b+n+1)-(b+1); for(register int i=1;i<=n;i++)aa[i]=lower_bound(b+1,b+len+1,a[i])-(b+1); for(register int i=1;i<=n;i++)aa[i]+=2; len+=100; for(register int i=n;i>=1;i--){ ni[i]=query(len-aa[i]-1); add(len-aa[i]); } memset(num,0,sizeof(num)); for(register int i=1;i<=n;i++){ shun[i]=query(aa[i]-1); add(aa[i]); } long long ans=0; for(register int i=1;i<=n;i++)ans=ans+shun[i]*ni[i]; cout<<ans<<endl; }
『Luogu 1637』三元上升子序列 (樹狀數組)