码迷,mamicode.com
首页 > 编程语言 > 详细

『Luogu 1637』三元上升子序列 (树状数组)

时间:2018-09-26 00:09:14      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:兴趣   org   clu   algo   names   lld   line   mem   def   

题目链接

题目描述

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』三元上升子序列 (树状数组)

标签:兴趣   org   clu   algo   names   lld   line   mem   def   

原文地址:https://www.cnblogs.com/Fang-Hao/p/9704215.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!