递增三元组
给定三个整数数组
A=[A1,A2,…AN],
B=[B1,B2,…BN],
C=[C1,C2,…CN],
请你统计有多少个三元组 (i,j,k) 满足:
1≤i,j,k≤N
Ai<Bj<Ck
输入格式
第一行包含一个整数 N。
第二行包含 N 个整数 A1,A2,…AN。
第三行包含 N 个整数 B1,B2,…BN。
第四行包含 N 个整数 C1,C2,…CN。
输出格式
一个整数表示答案。
数据范围
1≤N≤10^5,
0≤Ai,Bi,Ci≤10^5
输入样例:
3
1 1 1
2 2 2
3 3 3
输出样例:
27
分析:
题干很容易理解,从a,b,c 三个数组种各取一个数满足条件就视为一种情况。如果用暴力来做,就是使用三从循环,时间复杂度将达到O(n^3)当n大于1000时将无法承受。而且此题n最坏情况下还是10 ^5,所以大概猜测一下时间复杂度 为O(nlgn)是程序才可以接受。
然后对做法进行简单的分析:首先一定只能每一一个数组了,所以枚举a,b,c中的那个才能让枚举一次就能确定一种情况呢。。。。
枚举a,c的话理论上是一样的,没办法对离他远的那个进行约束,所以一定是枚举中间的数组b, 对于b中的每一个数字,其他两个从a,c选的数组都会被约束为,小于b[i] 和大于b[i] ,由于对于a,c是相互独立的事件,所以对于每个b【i】 只要从a中找到比他小的(不可以是等于) 数字的个数,和在c中大于b【i】的数字的个数,将二者相乘就是中间数字为b【i】的这种情况的所有情况数量了。
好了,现在思路很清晰了就可以着手写代码了:
code:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <string>
#include <deque>
using namespace std;
const int maxn=1e5+10;
int n;
long long res=0;
int len;
int a[maxn],b[maxn],c[maxn];
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]);
} // 读入a,b,c
sort(a,a+n);
sort(c,c+n); //为二分查找做准备
for(int i=0;i<n;i++){
int t1,t2;
int l=0,r=n-1;
while(l<r){ // 首先在a中查找最后一个小于b[i]的数字位置。
int mid=(l+r+1)/2;
if(a[mid]>=b[i]){
r=mid-1;
}
else l=mid;
}
t1=l+1; //a所有满足小于b[i]的数字个数
if(a[l]>=b[i]) t1=0;
l=0,r=n-1;
while(l<r){ // 首先在c中查找第一个大于b[i]的数字位置。
int mid=(l+r)/2;
if(c[mid]<=b[i]){
l=mid+1;
}
else r=mid;
}
t2=n-l; //c所有满足大于b[i]的数字个数
if(c[l]<=b[i]) t2=0;
res+=(long long )t1*t2; //这里注意了t1和t2 都是int类型的最大都是100000 ,相乘的话可能爆int 所以强转一下。
}
cout<<res;
return 0;
}
没有发现两个int相乘爆int的情况,让我一直无法AC,没办法当时只能用高精度存了res。
Code:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <string>
#include <deque>
using namespace std;
const int maxn=1e5+10;
int n;
int res[50];
int len;
int a[maxn],b[maxn],c[maxn];
void myfun(long long temp){
int index=0;
while(temp){
res[index]=res[index]+temp%10;
if(res[index]>=10){
res[index+1]=res[index+1]+res[index]/10;
res[index]%=10;
}
index++;
temp/=10;
}
len=max(len,index);
}
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]);
}
sort(a,a+n);
sort(c,c+n);
for(int i=0;i<n;i++){
int t1,t2;
int l=0,r=n-1;
while(l<r){
int mid=(l+r+1)/2;
if(a[mid]>=b[i]){
r=mid-1;
}
else l=mid;
}
t1=l+1;
if(a[l]>=b[i]) t1=0;
l=0,r=n-1;
while(l<r){
int mid=(l+r)/2;
if(c[mid]<=b[i]){
l=mid+1;
}
else r=mid;
}
t2=n-l;
if(c[l]<=b[i]) t2=0;
myfun((long long)t1*t2);
}
if(res[len]==0) len-=1;
for(int i=len;i>=0;i--){
cout<<res[i];
}
if(len==-1) cout<<0;
cout<<endl;
}
用了大整数加法后,依然是无法AC 这是才发现了问题的真正所在,哎,很难受就是了,以后一定注意呜呜呜。