『Luogu 1637』三元上升子序列 (树状数组)
Posted fang-hao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了『Luogu 1637』三元上升子序列 (树状数组)相关的知识,希望对你有一定的参考价值。
题目描述
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』三元上升子序列 (树状数组)的主要内容,如果未能解决你的问题,请参考以下文章