洛谷 P1637 三元上升子序列

洛谷 P1637 三元上升子序列

题目链接

题目描述

Erwin 最近对一种叫 thair 的东西巨感兴趣。。。

在含有 n n n 个整数的序列 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an 中,三个数被称作thair当且仅当 i < j < k i<j<k i<j<k a i < a j < a k a_i<a_j<a_k ai<aj<ak

求一个序列中 thair 的个数。

输入格式

开始一行一个正整数 n n n,

以后一行 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an

输出格式

一行一个整数表示 thair 的个数。

样例

输入 #1

4
2 1 3 4

输出 #1

2

输入 #2

5
1 2 2 3 4

输出 #2

7

典型的权值线段树,将数据先离散,然后对每个数 a [ i ] a[i] a[i] 在线段树中找比它小的 l [ i ] l[i] l[i] r [ i ] r[i] r[i] 即可,最后累加 l [ i ] ∗ r [ i ] l[i]*r[i] l[i]r[i] 就是答案,AC代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e4+5;
typedef long long ll;
int n,m,k;
ll a[N],l[N],r[N],tree[N<<2];
vector<ll>v;
int getpos(ll x){
    
    
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}

void pushup(int i)
{
    
    
    tree[i]=tree[i<<1]+tree[i<<1|1];
}

void build(int i,int l,int r)
{
    
    
    if(l==r)
    {
    
    
        tree[i]=0;
        return ;
    }
    int mid=l+r>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    pushup(i);
}

void update(int i,int l,int r,int x,int k)
{
    
    
    if(l==r)
    {
    
    
        tree[i]+=k;
        return ;
    }
    int mid=l+r>>1;
    if(x<=mid) update(i<<1,l,mid,x,k);
    else update(i<<1|1,mid+1,r,x,k);
    pushup(i);
}

ll query(int i,int l,int r,int m,int n)
{
    
    
    if(m<=l&&r<=n) return tree[i];
    int mid=l+r>>1;
    ll ans=0;
    if(m<=mid) ans+=query(i<<1,l,mid,m,n);
    if(n>mid) ans+=query(i<<1|1,mid+1,r,m,n);
    return ans;
}

int main(){
    
    
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
    
    
        scanf("%d",&a[i]);
        v.push_back(a[i]);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    n=v.size();
    for(int i=1;i<=m;i++){
    
    
        int pos=getpos(a[i]);
        if(pos!=1) l[i]=query(1,1,n,1,pos-1);
        update(1,1,n,getpos(a[i]),1);
    }
    memset(tree,0,sizeof((tree)));
    for(int i=m;i>=1;i--){
    
    
        int pos=getpos(a[i]);
        if(pos!=n) r[i]=query(1,1,n,getpos(a[i])+1,n);
        update(1,1,n,getpos(a[i]),1);
    }
    ll ans=0;
    for(int i=1;i<=m;i++) ans+=l[i]*r[i];
    printf("%lld",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43765333/article/details/108626814