C++ increment triples (enumeration, prefix sum)

Given three integer arrays
A=[A1,A2,…AN],
B=[B1,B2,…BN],
C=[C1,C2,…CN], please count how many triples (i ,j,k)
satisfies:
1≤i,j,k≤N
Ai<Bj<Ck
input format The
first line contains an integer N. The second line contains N integers A1, A2,...AN. The third line contains N integers B1, B2,...BN.
The fourth line contains N integers C1, C2,...CN.
Output format
An integer represents the answer.
Data range
1≤N≤105,0≤Ai,Bi,Ci≤105
Input example:
3
1 1 1
2 2 2
3 3 3
Output example:
27

The key to this question is to find that a[i] and c[k] in each incremental triple are bound by b[j], so the number of triples should be calculated by enumerating b[j]. At the same time, the error-prone point of this question is when counting the number of occurrences of each value, the subscript of the last element is determined by the maximum value of the data, and the maximum value of the data range is used uniformly.
AC code:

#include<stdio.h>
#include<string.h>

const int N=100010;
typedef long long LL;

int n;
int a[N],b[N],c[N];
int cnt[N],s[N];
int anum[N],cnum[N];

int main()
{
    
    
    scanf("%d",&n);
    //因为要计算值出现次数的前缀和,把所有值+1避免占用0下标
    for(int i=1;i<=n;++i){
    
    scanf("%d",&a[i]);++a[i];}
    for(int i=1;i<=n;++i){
    
    scanf("%d",&b[i]);++b[i];}
    for(int i=1;i<=n;++i){
    
    scanf("%d",&c[i]);++c[i];}

    //统计a数组中各个值出现的次数
    for(int i=1;i<=n;++i) ++cnt[a[i]];
    //计算a数组中各个值出现次数的前缀和
    //因为值的范围是1~100001,cnt的最后一项为cnt[100001]
    for(int i=1;i<N;++i) s[i]=s[i-1]+cnt[i];
    //anum[i]中保存a中小于b[i]的数的个数
    for(int i=1;i<=n;++i) anum[i]=s[b[i]-1];

    memset(cnt,0,sizeof(cnt));
    memset(s,0,sizeof(s));
    for(int i=1;i<=n;++i) ++cnt[c[i]];
    for(int i=1;i<N;++i) s[i]=s[i-1]+cnt[i];
    //cnum[i]中保存c中大于b[i]的数的个数
    for(int i=1;i<=n;++i) cnum[i]=s[N-1]-s[b[i]];

    LL ans=0;//统计答案
    for(int i=1;i<=n;++i) ans+=(LL)anum[i]*cnum[i];

    printf("%lld",ans);
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44643644/article/details/108854432