暴力方法(只能过一半的数据)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 10010;
int a[N],b[N],c[N];
int n;
int main()
{
cin >> n;
for(int i = 0; i < n; i++) scanf("%d",&a[i]);
for(int i = 0; i < n; i++) scanf("%d",&b[i]);
for(int i = 0; i < n; i++) scanf("%d",&c[i]);
ll res = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
for(int k = 0; k < n; k++)
if(c[k] > b[j] && b[j] > a[i]) res++;
cout << res <<endl;
return 0;
}
跟着y总写的还是不明白
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 100010;
int n;
int a[N],b[N],c[N];
int as[N]; // as[i]表示a[]中小于 b[i] 的数的个数
int cs[N]; // cs[i]表示c[]中小于 b[i] 的数的个数
int cnt[N],s[N]; // cnt[i]用来存储数值是i的个数;s[i] 存储数值小于等于 i 的总数
int main()
{
cin >> n;
for(int i = 0; i < n; i++) scanf("%d",&a[i]), a[i]++;
for(int i = 0; i < n; i++) scanf("%d",&b[i]), b[i]++;
for(int i = 0; i < n; i++) scanf("%d",&c[i]), c[i]++;
//as前缀和处理
for(int i = 0; i < n; i++) cnt[a[i]]++;
for(int i = 1; i < N; i++) s[i] = s[i - 1] + cnt[i];
for(int i = 0; i < n; i++) as[i] = s[b[i] - 1];
memset(cnt,0,sizeof cnt);
memset(s,0,sizeof s);
//cs前缀和处理
for(int i = 0; i < n; i++) cnt[c[i]]++;
for(int i = 1; i <= N; i++) s[i] = s[i - 1] + cnt[i];
for(int i = 0; i < n; i++) cs[i] = s[N] - s[b[i]];
//枚举所有的结果
ll res = 0;
for(int i = 0; i < n; i++) res += (ll)as[i] * cs[i];
cout << res << endl;
return 0;
}
二分的方法(彻彻底底的自己一点点想出来的)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 100010;
typedef long long ll;
int a[N],b[N],c[N];
int n;
int main()
{
cin >> n;
for(int i = 1 ; i <= n; i++) cin >> a[i];
for(int i = 1 ; i <= n; i++) cin >> b[i];
for(int i = 1 ; i <= n; i++) cin >> c[i];
sort(a+1,a+n+1); // 分别给a,c数组排序 sort()注意下表从1开始,n结束,sort要在最后一个元素的下一位!
sort(c+1,c+n+1);
// 调试代码
/* for(int i = 1; i <= n; i++) cout << a[i] << " ";
cout << endl;
for(int i = 1; i <= n; i++) cout << c[i] << " ";
cout << endl;
*/
ll res = 0;
for(int i = 1; i <= n; i++)
{
int la = 1,lc = 1,ra = n,rc = n;
while(la < ra)
{
int mid = (la + ra) / 2;
// cout << mid <<endl;
if(a[mid] >= b[i]) ra = mid;
else la = mid + 1;
}
//此时a[la] = a[ra] = 最后一个小于或等于 b[i] 的位置
int x;
if(a[la] >= b[i]) x = la - 1; // 此时a[la]是第一个小于等于b[i]的数,a[la]左边的数都是小于等于b[i]的 个数在数值上等于 la-1
else x = la; // 说明a[i]中所有的数都是小于b[i]的,此时la的在数值上就等于小于b[i]的个数
while(lc < rc)
{
int mid = (lc + rc + 1) / 2;
if(c[mid] <= b[i]) lc = mid;
else rc = mid - 1;
}
//此时c[lc] = c[rc] = 第一个大于或等于 b[i] 的位置
int y;
if(c[lc] <= b[i]) y = lc + 1;
else y = lc;
// 调试代码
// cout << x << " " << y << endl;
//由于下表有一个减一关系,la恰好就是小于b[i]的个数,
res += (ll)x * (n - y + 1); // 注意这里x和y都是范围是0~1e5,相乘有可能爆int,先把x转成long long
}
cout << res << endl;
return 0;
}
二刷前缀和法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 100010;
int n;
int A[N],B[N],C[N];
int AS[N]; // AS[i]表示A数组中小于b[i]的元素个数
int CS[N]; // CS[i]表示C数组中大于b[i]的元素个数
int cnt[N];// cnt[i]表示A/C数组中等于i的元素的个数,cnt[A[i]] --> 数组中A[i]的个数
int s[N]; // s[i]前缀和数组,表示cnt[]中小于等于i的个数之和
int main()
{
cin >> n;
for(int i = 0; i < n; i++) scanf("%d",&A[i]),A[i]++;
for(int i = 0; i < n; i++) scanf("%d",&B[i]),B[i]++;
for(int i = 0; i < n; i++) scanf("%d",&C[i]),C[i]++;
//解释一下 上面三行+1 的操作
//因为A[i]、B[i]、C[i]的取值范围是[0,1e5] --> 那么cnt[i]中的元素会从0开始存 --> 前缀和数组要求cnt[i]从1开始存
//否则要额外处理越界情况,为了减少不必要的麻烦,在读入A[i],B[i],C[i]之后统一都加上一个1,即A[i]、B[i]、C[i]的取值范围是[1,1e5+1]
//此时cnt[]的范围是[1,1e5+1] --> 保证了s[]求前缀和时,cnt[]从1开始的条件,s[i] = s[i - 1] + cnt[i]
//先处理A[]
for(int i = 0; i < n; i++) cnt[A[i]]++;
for(int i = 1; i <= N; i++) s[i] = s[i - 1] + cnt[i]; // s[i] 表示小于等于i的元素个数有多少个
for(int i = 0; i < n; i++) AS[i] = s[B[i] - 1]; // 记好AS[i]的意义
memset(cnt, 0, sizeof cnt);
memset(s, 0, sizeof s);
for(int i = 0; i < n; i++) cnt[C[i]]++;
for(int i = 1; i <= N; i++) s[i] = s[i - 1] + cnt[i];
for(int i = 0; i <= n; i++) CS[i] = s[N] - s[B[i]]; // C[]中小于等于N的个数 - C[]中小于等于B[i]的个数 = C[]中大于等于B[i]的个数
ll res = 0;
//枚举每一个B[i]
for(int i = 0; i < n; i++) res += (ll)AS[i] * CS[i];
cout << res;
return 0;
}