小练练练习

递增三元组

给定三个整数数组

A=[A1,A2,…AN], B=[B1,B2,…BN], C=[C1,C2,…CN],

请你统计有多少个三元组 (i,j,k) 满足:

1≤i,j,k≤N Ai

第二行包含 N 个整数 A1,A2,…AN。

第三行包含 N 个整数 B1,B2,…BN。

第四行包含 N 个整数 C1,C2,…CN。

输出格式 一个整数表示答案。

数据范围 1≤N≤105, 0≤Ai,Bi,Ci≤105

**思路:**由于数据范围是le5,所以一般的N的三方复杂度必然会TLE.
能够运用前缀数组分别存储a和c的前缀和 (因为他们两个都跟b有联系,可以并且相互独立) as存储a数组的1~N的前缀和,cs则存储c数组 1~N的前缀和,分别存储比b[i]小的所有数的个数和比b[i]大的所有数的个数。循环遍历B数组 找到比b[i]小的个数和比b[i]大的个数运用乘法法则 然后再累加即可。

#include 
using namespace std;
const int N=1e5+10;
int a[N],b[N],c[N];
int as[N],cs[N];  //
int cnt[N];
int  s[N];
int main(){
    int n;
    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]++;
    }
    // 统计a[i]中数出现的次数
    for(int i=0;i<n;i++) cnt[a[i]]++;
    // a数组中小于b[i]的所有数的前缀和
    for(int i=1; i<N;i++) s[i]+=s[i-1]+cnt[i];
    // 预处理a数组中比b数组中每个数小的个数
    for(int i=0;i<n;i++) as[i] = s[b[i]-1]; //在a中比b[i]小的个数 b[i]-1
    
    memset(cnt,0,sizeof(cnt));
    memset(s,0,sizeof(s));
    for(int i =0;i<n;i++) cnt[c[i]]++;   //找出c数组中每个数出现的次数
    for(int i=1;i<N;i++) s[i] =s[i-1]+cnt[i]; //前缀和累加c数组中出现的次数
    for(int i=0;i<n;i++) cs[i] = s[N-1]-s[b[i]];
    
     long long res= 0;
    for(int i=0;i<n;i++){
       res +=(long long )as[i]*cs[i];  //a数组和c数组的个数累成可能会爆int 所以强制转化为longlong
    }
    printf("%lld",res); 
}

在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

牛牛习惯用 8 位数字表示一个日期,其中,前 4 位代表年份,接下来 2 位代表月份,最后 2 位代表日期。

显然:一个日期只有一种表示方法,而两个不同的日期的表示方法不会相同。

牛牛认为,一个日期是回文的,当且仅当表示这个日期的 8 位数字是回文的。

现在,牛牛想知道:在他指定的两个日期之间(包含这两个日期本身),有多少个真实存在的日期是回文的。

一个 8 位数字是回文的,当且仅当对于所有的 i(1≤i≤8) 从左向右数的第 i 个数字和第 9−i 个数字(即从右向左数的第 i
个数字)是相同的。

思路: 因为每个日期是八位 所以先枚举前面一半 再翻转过来保证是回文数,然后在判断是否合法并且在范围中

#include 
using namespace std;
int res=0;
int months[13] ={0,31,28,31,30,31,30,31,31,30,31,30,31};

bool check_valid(int n){
   int year = n/10000;
   int month = n%10000/100;
   int day = n%100;
    
 if(month ==0||month>12) return false;  //判断日是否合法
  if(day==0||month!=2&&day>months[month]) return false;   //判断除2月外得天数是否合法
  
  if(month ==2){
      int temp =year%4==0&&year%100||year%400==0;
      if(day==0||day>months[2]+temp) return false;   //判断2月是否合法
  }
  return true;   //返回日期合法
}
int main(){
    int date1,date2;
    scanf("%d%d",&date1,&date2);
    for(int i=1000;i<=9999;i++){
        int m=i,date =i;
        
        for(int j=0;j<4;j++){
            date=date*10+m%10;
            m/=10;
        }
      if(date1<=date&&date<=date2&&check_valid(date)) res++;  
        
    }
    printf("%d",res);
    return 0;
}

你可能感兴趣的:(算法,数据结构,c++,蓝桥)