算法1
C++ 代码
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const int N=100000+6;
int n,a[N],b[N],c[N];
long long res=0;
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<n;i++) cin>>c[i];
sort(a,a+n);sort(b,b+n);sort(c,c+n);
for(int i=0;i<n;i++)
{
int low_a=0,right_a=n-1;
while(low_a<right_a)
{
int mid=(low_a+right_a+1)>>1;
if(a[mid]<b[i]) low_a=mid;
else right_a=mid-1;
}
if(a[low_a]>=b[i]) low_a=-1;
int low_b=0,right_b=n-1;
while(low_b<right_b)
{
int mid =(low_b+right_b)>>1;
if(c[mid]>b[i]) right_b=mid;
else low_b=mid+1;
}
if(c[low_b]<=b[i]) low_b=n;
res+=(long long)(low_a+1)*(n-low_b);
}
cout<<res<<endl;
return 0;
}
算法2
C++ 代码
#include <iostream>
#include <string.h>
using namespace std;
const int N=100005;
int n,a[N],b[N],c[N];
int cnt=0;
int num[N],s[N];
int as[N],cs[N];
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<n;i++) cin>>c[i];
for(int i=0;i<n;i++) num[a[i]]++;
for(int i=0;i<=N;i++) s[i]=s[i-1]+num[i];
for(int i=0;i<n;i++) as[i]=s[b[i]-1];
memset(num,0,sizeof(num));
memset(s,0,sizeof(s));
for(int i=0;i<n;i++) num[c[i]]++;
for(int i=0;i<=N;i++) s[i]=s[i-1]+num[i];
for(int i=0;i<n;i++) cs[i]=s[N]-s[b[i]];
long long res=0;
for(int i=0;i<n;i++)
res+=(long long)as[i]*cs[i];
cout<<res<<endl;
return 0;
}
算法3
C++ 代码
#include <iostream>
using namespace std;
const int N=10000;
int n,a[N],b[N],c[N];
int cnt=0;
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<n;i++) cin>>c[i];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
if(a[i]<b[j]&&b[j]<c[k])
cnt++;
cout<<cnt<<endl;
return 0;
}
为啥不从0开始就不行啊?
可以啊,前缀和从0开始对0要单独判断一下就行
那个小学乘法原理确实把我都笑了哈哈哈哈,果然是胎教
有哪位大佬帮我看一下前缀和为啥过不了最后一个数据,边界问题好难搞
include[HTML_REMOVED]
include[HTML_REMOVED]
include[HTML_REMOVED]
include[HTML_REMOVED]
include[HTML_REMOVED]
using namespace std;
const int N=100010;
int n,a[N],b[N],c[N];
int num[N],s[N];
int as[N],cs[N];
int main(){
cin>>n;
for(int i=1;i<=n;i)cin>>a[i];
for(int j=1;j<=n;j) {cin>>b[j];};
for(int k=1;k<=n;k) cin>>c[k];
//处理as
for(int i=1;i<=n;i) num[a[i]];//记录a[i]出现的次数
for(int i=1;i<=N;i) s[i]=s[i-1]+num[i]; //递推求得关于a[i]的所有前缀和
for(int i=1;i<=n;i) as[i]=s[b[i]-1]; //as代表比b[i]小的数的前缀和
memset(num,0,sizeof num);
memset(s,0,sizeof s);
//处理cs
for(int i=1;i<=n;i) num[c[i]];//记录c[i]出现的次数
for(int i=1;i<=N;i) s[i]=s[i-1]+num[i];//递推求得关于c[i]的所有前缀和
for(int i=1;i<=n;i) cs[i]=s[N-1]-s[b[i]];//cs代表比b[i]大的数的前缀和
//求结果
long long res=0;
for(int i=1;i<=n;i) {
res+=(long long)as[i]*cs[i];
}
cout<<res;
return 0;
}
你a[i],b[i],c[i]是可能取0的,当他们取0时,num[0]++,也就是有值,所以你算前缀和时要加上它,你把那几段for(int i=1;i<=N;i) s[i]=s[i-1]+num[i]; 改成for(int i=0;i<=N;i) s[i]=s[i-1]+num[i]; 就行
改成0开始就ac了
#include[HTML_REMOVED]
using namespace std;
const int N=100010;
int n,a[N],b[N],c[N];
int num[N],s[N];
int as[N],cs[N];
int main(){
cin>>n;
for(int i=1;i<=n;i) cin>>a[i];
for(int j=1;j<=n;j) cin>>b[j];
for(int k=1;k<=n;k) cin>>c[k];
//处理as
for(int i=1;i<=n;i) num[a[i]];//记录a[i]出现的次数
for(int i=0;i<=N;i) s[i]=s[i-1]+num[i]; //递推求得关于a[i]的所有前缀和
for(int i=1;i<=n;i) as[i]=s[b[i]-1]; //as代表比b[i]小的数的前缀和
memset(num,0,sizeof num);
memset(s,0,sizeof s);
//处理cs
for(int i=1;i<=n;i) num[c[i]];//记录c[i]出现的次数
for(int i=0;i<=N;i) s[i]=s[i-1]+num[i];//递推求得关于c[i]的所有前缀和
for(int i=1;i<=n;i) cs[i]=s[N-1]-s[b[i]];//cs代表比b[i]大的数的前缀和
//求结果
long long res=0;
for(int i=1;i<=n;i) {
res+=(long long)as[i]*cs[i];
}
cout<<res;
return 0;
}
谢谢!!
前缀和for(int i=0;i<=N;i++) s[i]=s[i-1]+num[i];为啥一定要加等于呢?不加结果就不对
因为后面用了s[N],如果这里不把前缀和计算到s[N]的话,s[N]的值就是0哈
那为很么当从0开始求前缀和的时候0-1不是-1数组下标不正确了吗
我也想问
我也好奇为什么必须从0开始,不从0开始,过不了
我感觉写法是有问题的,下标会越界。先使s[0]=num[0],然后再让下标从1开始会比较好一些。如果A,C中出现0的时候,s[0]=零的个数。
我也想知道,大佬现在清楚了吗
从1开始只是为了避免一些边界问题
那为很么当从0开始求前缀和的时候0-1不是-1数组下标不正确了吗
我也想知道,大佬现在清楚了吗
用那个前缀和做的那个,我想问一下y总为什么每次都要加1啊hhh
边界