萌新,27pts,求调(有批注)
查看原帖
萌新,27pts,求调(有批注)
584893
封禁用户楼主2024/10/6 22:31

思路如下:


他让求三元上升子序列,我就先求二元,一个数可以作为顺序列里的小数(be数组),也可以是大数(en数组),那么当这个数是一个数列的大数,另一个数列的小数时,就能组成三元上升子子序列

举个例子:1 2是顺序列,2 3也是, 那么1 2 3就是三元上升子序列,结果就是2的be[2]*en[2]

(本人太弱了,不知道思路对不对,请各位大佬指点)

//
//  main.cpp
//  三元上升子序列
//
//  Created by hjc on 2024/10/6.
//


#include <iostream>
#include <queue>
#include <map>
using namespace std;
const int N=3*1e5+100;
map<long long,long long>mp;
long long a[N],b[N],be[N],en[N];
//a为原数组排序后结果,b为离散化结果,be代表这个数作为开头个数,en代表这个数作为结尾的个数
void msort(long long l,long long r){
    //二分
    if(l>=r)return ;
    int mid=(l+r)>>1;
    msort(l,mid);
    msort(mid+1,r);
    int nl=l,nr=mid+1,num1=0,cnt=0;
    while(nl<=mid&&nr<=r){
        if(b[nl]>b[nr]){
            a[nl-l+nr-mid]=b[nl];
            be[b[nl]]+=cnt;
            nl++;
        }
        else{
            a[nl-l+nr-mid]=b[nr];
            en[b[nr]]+=mid-nl+1;
            cnt++;
            nr++;
        }
    }
    while(nl<=mid){
        a[nl-l+nr-mid]=b[nl];
        be[b[nl]]+=cnt;
        nl++;
    }
    while(nr<=r){
        a[nl-l+nr-mid]=b[nl];
        nr++;
    }
    for(int i=l;i<=r;i++){
        b[i]=a[i-l+1];
    }
}
int main(int argc, const char * argv[]){
    int n;
    cin>>n;
    a[0]=1e9;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i]=a[i];
    }
    //离散化
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        long long bi=b[i];
        b[i]=upper_bound(a+1,a+1+n,b[i])-a-mp[b[i]]-1;
        mp[bi]++;
    }
    msort(1,n);
    long long ans=0;
    for(int i=1;i<=n;i++){
//        cout<<be[i]<<" "<<en[i]<<"\n";
        ans+=en[i]*be[i];
    }
    cout<<ans<<endl;
}

2024/10/6 22:31
加载中...