三元上升子序列

题目链接:https://www.luogu.com.cn/problem/P1637

题意:

给定数组,求i<j<k且a[i]<a[j]<a[k]的三元组数量

思路:

不妨枚举a[j]

这样我们只需要知道 它前面的数中 有多少个小于它的

它后面的数 有多少个大于它的

可以通过两个树状数组维护

将树状数组数组视为桶(因此边界为max(a[i])

每次可以快速查询大小在[1,a[i]]范围内的 数的数量。

已知已经枚举的数的数量

求出局部答案然后累加即可

思想和树状数组求逆序对完全一致

int s[maxn];
int t[maxn];
int n;
int lowerbit(int x){
    return x&-x;
}
void add(int p,int x,int opt){
    while(p<=1e5){
        if(opt==1)s[p]+=x;else t[p]+=x;
        p+=lowerbit(p);
    }
}
int query(int p,int opt){
    int res=0;
    while(p){
        if(opt==1)res+=s[p];else res+=t[p];
        p-=lowerbit(p);
    }   
    return res;
}
void solve(){
    cin>>n;
    vector<int>a(n+1);
    rep(i,1,n)cin>>a[i];
    rep(i,1,n){
        add(a[i],1,1);
    }
    int ans=0;
    rep(i,1,n){
        int num=i-1;
        int equal=query(a[i],2)-query(a[i]-1,2);
        int les=query(a[i],2)-equal;

        int big=num-query(a[i],2);//[1,i-1]所有大于a[i]的数的数量
        int total_big=n-query(a[i],1);//[1,n]所有大于a[i]的数的数量
        int dif=total_big-big;//[i+1,n]所有大于a[i]的数的数量

        ans+=les*1*dif;
        add(a[i],1,2);
    }
    cout<<ans<<endl;
}
posted @ 2025-05-09 15:56  Marinaco  阅读(18)  评论(0)    收藏  举报
//雪花飘落效果