1.AcWing 1210.连号区间数
分析思路
由题意是在 1∼N 的某个排列中有多少个连号区间,所以每个数出现并且不重复!
如果是连续的,那么Max-Min==j-i([i,j])
代码实现
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10010,INF = 100000000;
int a[N];
int main()
{int n;cin>>n;int count=0;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++)//枚举区间的左端点{int Max=-INF,Min=INF;for(int j=i;j<n;j++)//枚举区间的右端点{Max=max(Max,a[j]);Min=min(Min,a[j]);if(Max-Min==j-i) count++;}}cout<<count<<endl;return 0;
}
2.AcWing 1236.递增三元组
分析思路
由题意可知,需要从A、B、C数组中各取一个,使得A<B<C,所以我们来枚举B数组(由于时间复杂度的限制只能枚举一个数组),这样A,C是独立的互不影响的,只与B数组的大小有关,然后从A中找到小于B的个数、从C中找到大于B的个数,两者相乘。
排序+二分:先对A、C数组进行排序然后用二分求出A中小于B的第一个个数的位置和C中大于B的第一个位置。
前缀和:
代码实现
排序+二分:
#include<iostream>
#include<algorithm>using namespace std;
const int N=100010;
typedef long long LL;
int a[N],b[N],c[N];int main()
{int n;cin>>n;for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);for (int i = 1; i <= n; i ++ ) scanf("%d", &b[i]);for (int i = 1; i <= n; i ++ ) scanf("%d", &c[i]);sort(a+1,a+n+1);sort(c+1,c+n+1);LL res=0;for(int i=1;i<=n;i++){int l=1,r=n;while(l<r){int mid=(l+r+1)/2;if(a[mid]<b[i]) l=mid;else r=mid-1;}if (a[l] < b[i]) {int temp=l;l=1,r=n;while(l<r){int mid=(l+r)/2;if(c[mid]>b[i]) r=mid;else l=mid+1;}if(c[r]>b[i]) res+=(LL)(temp)*(LL)(n-l+1);}}cout<<res<<endl;return 0;
}
前缀和:
3个数组的所有数都加1,是因为在不影响数与数之间的大小关系下,让该行代码s[b[i] - 1];
避免出现b[i]为0的情况导致空指针异常
#include<iostream>
#include<algorithm>using namespace std;
const int N=100010;
typedef long long LL;
int a[N],b[N],c[N],s[N],t[N],x[N],y[N];int main()
{int n;cin>>n;for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]),a[i]++;for (int i = 1; i <= n; i ++ ) scanf("%d", &b[i]),b[i]++;for (int i = 1; i <= n; i ++ ) scanf("%d", &c[i]),c[i]++;LL res=0;for(int i=1;i<=n;i++){s[a[i]]++;t[c[i]]++;}for(int i=1;i<=N;i++){x[i]=x[i-1]+s[i];y[i]=y[i-1]+t[i];}for(int i=1;i<=n;i++){res+=(LL)(x[b[i]-1])*(LL)(y[N]-y[b[i]]);}cout<<res<<endl;return 0;
}
3.AcWing 1245.特别数的和
分析思路
每次取出个位数判断是否满足要求即可!
字符型数组转化成整型:
int x=0;
for(int i=0;i<s.size();i++)
{
x=x*10+s[i]-'0';
}
代码实现
#include<iostream>using namespace std;
int main()
{int n;cin>>n;int res=0;for(int i=1;i<=n;i++){int x=i;while(x){int t=x%10;//取个位数x/=10;//去掉个位if(t==1||t==2||t==0||t==9) {res+=i;break;//只要存在指定数字结束本次循环}}}cout<<res<<endl;return 0;
}
4.AcWing 1204. 错误票据
分析思路
先对数组进行排序操作,然后遍历如果存在前一个和后一个相等则为重号ID,如果存在当a[i]>=a[i-1]+2,则两者之前存在缺失ID即a[i]-1。
代码实现
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>using namespace std;const int N = 10010;int n;
int a[N];int main()
{int cnt;cin >> cnt;string line;getline(cin, line); // 忽略掉第一行的回车while (cnt -- ){getline(cin, line);stringstream ssin(line);while (ssin >> a[n]) n ++ ;}sort(a, a + n);int res1, res2;for (int i = 1; i < n; i ++ )if (a[i] == a[i - 1]) res2 = a[i]; // 重号else if (a[i] >= a[i - 1] + 2) res1 = a[i] - 1; // 断号cout << res1 << ' ' << res2 << endl;return 0;
}
还可以使用以下代码对数组进行读入:
int x, i = 0;cin >> x;//过滤while(cin >> x) a[i++] = x;
5.AcWing 466.回文日期
分析思路
①枚举回文数(年份的范围是在1000~10000)
先枚举前四位,然后算出八位数的日期
int res=0;for(int i=1000;i<10000;i++){int r=i,x=i;//形成八位数的日期for(int i=0;i<4;i++) r=r*10+x%10,x/=10;if(r>=date1&&r<=date2&&check(r)) res++;}
②判断是否在范围内
③判断日期是否合法
先开一个每个月份天数的集合,先判断月份(除二月之外)、天数是否满足,然后根据平年闰年对二月的天数进行讨论(平年-28天 闰年-29天)
bool check(int data)
{int year=data/10000;int month=data%10000/100;int day=data%100;if(!month||month>12||!day) return false;if(month!=2&&day>days[month]) return false;if(month==2){bool flag=year%100&&year%4==0||year%400==0;if(day>28+flag)//如果是闰年则二月是29天需要+100return false;}return true;
}
代码实现
#include<iostream>
#include<algorithm>using namespace std;
int days[13]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool check(int data)
{int year=data/10000;int month=data%10000/100;int day=data%100;if(!month||month>12||!day) return false;if(month!=2&&day>days[month]) return false;if(month==2){bool flag=year%100&&year%4==0||year%400==0;if(day>28+flag)//如果是闰年则二月是29天需要+100return false;}return true;
}
int main()
{int date1,date2;cin>>date1>>date2;int res=0;for(int i=1000;i<10000;i++){int r=i,x=i;//形成八位数的日期for(int i=0;i<4;i++) r=r*10+x%10,x/=10;if(r>=date1&&r<=date2&&check(r)) res++;}cout<<res<<endl;return 0;
}
6.AcWing 2867.回文日期(蓝桥杯真题)
分析思路
在上一题的基础上加上对回文日期的判断(双指针方法)和AB型日期的特判
代码实现
#include<iostream>
#include<algorithm>using namespace std;
int days[13]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool check(int data)
{int year=data/10000;int month=data%10000/100;int day=data%100;if(!month||month>12||!day) return false;if(month!=2&&day>days[month]) return false;if(month==2){bool flag=year%100&&year%4==0||year%400==0;if(day>28+flag)//如果是闰年则二月是29天需要+100return false;}return true;
}
bool check1(string data)
{int l=data.length();for(int i=0,j=l-1;i<j;i++,j--){if(data[i]!=data[j]) return false;}return true;
}
bool check2(string data)
{if(check1(data)){if(data[0]!=data[1]&&data[2]==data[0]&&data[3]==data[1]) return true;else return false;}
}
int main()
{int date1;int flage=0;cin>>date1;int res1=0,res2=0;for(int i=date1+1;i<=99999999;i++){if(check(i)){string s=to_string(i);if(check1(s)&&!flage)//回文判断{res1=i;flage=1;} if(check2(s))//回文特判{res2=i;break;}}}cout<<res1<<endl;cout<<res2<<endl;return 0;
}