递增三元组描述
前缀和实现思想:
- 数据输入:计算的输入数据后自增,便于计算前缀和且不影响其大小关系。
for(int i = 1;i <= n;i ++) cin>>a[i],a[i]++; // 便于下式前缀和的计算
for(int i = 1;i <= n;i ++) cin>>b[i],b[i]++;
for(int i = 1;i <= n;i ++) cin>>c[i],c[i]++;
- 计算AS和CS:根据已知Ai<Bi<Ci,当确定了Bi就能得出A中小于Bi的个数ASi和C中大于Bi的个数CSi,计算CSi*ASi即为遍历Bi时刻得到的三元组个数。
// 开始计算as[]
for(int i = 1;i <= n;i ++) cnt[a[i]] ++; // 元素出现的个数
for(int i = 1;i < N;i ++) s[i] = s[i-1] + cnt[i]; // 不大于i的个数
for(int i = 1;i <= n;i ++) as[i] = s[b[i]-1]; // 小于b[i]的数目数组
// 开始计算cs[]
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]; // 不大于i的个数
for(int i = 1;i <= n;i ++) cs[i] = n - s[b[i]]; // 元素总数-小于或者等于b[i]的数目
- 注意点:改题目数据大,所以用long long
res += (long long)as[i]*cs[i];
完整代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e6;
int as[N],cs[N],a[N],b[N],c[N],s[N],cnt[N];
int n;
int main(){
cin>>n;
// 输入数据
for(int i = 1;i <= n;i ++) cin>>a[i],a[i]++; // 便于下式前缀和的计算
for(int i = 1;i <= n;i ++) cin>>b[i],b[i]++;
for(int i = 1;i <= n;i ++) cin>>c[i],c[i]++;
// 开始计算as[]
for(int i = 1;i <= n;i ++) cnt[a[i]] ++;
for(int i = 1;i < N;i ++) s[i] = s[i-1] + cnt[i]; // 不大于i的个数
for(int i = 1;i <= n;i ++) as[i] = s[b[i]-1]; // 小于b[i]的数目数组
// 开始计算cs[]
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];
for(int i = 1;i <= n;i ++) cs[i] = n - s[b[i]];
// 开始遍历b[]
long long res = 0;
for(int i = 1;i <= n;i ++)
res += (long long)as[i]*cs[i];
cout<<res<<endl;
return 0;
}