蓝桥杯冲刺
1、贪心算法
1、反悔性质的
priority_queue用法:
定义priority_queue<元素类型, 底层容器类型, 比较函数对象类型> 队列名;
推荐洛谷:P2949 ——绿题> https://www.luogu.com.cn/problem/P2949
(2)比较函数:greater
自定义:struct CompareTask { bool operator()(const Task& a, const Task& b) { return a.priority > b.priority; } };
(3)适用题目:Top K问题、合并K个有序链表、Dijkstra算法(最短路)
注意ans有时初始化为0
2、位运算
unsigned int x=n&0xffff; unsigned int high=n>>16;
3、cin cout输入输出流
洛谷P1469找筷子问题,用cin cout写会超时,因为在C++中,cin和cout默认与C标准输入输出流保持同步(ios::sync_with_stdio(true)),这会带来额外的性能开销。此外,cout在输出时会先将数据存入缓冲区再刷新,而大量数据的缓冲操作会显著降低效率。相比之下,scanf和printf是C语言中更底层的格式化输入输出函数,没有流同步和缓冲区管理的额外步骤,因此在处理大规模数据时速度更快。
可添加ios::sync_with_stdio(false); cin.tie(0);可提高速度。或者用scanf printf
4、枚举
回文质数:有偶数位的回文数都不会是质数,除了11
洛谷p1217,谨防tle,需要对左端点进行偶数剔除,然后左右端点间每次+2来遍历,减少时间损失。
回文的判断代码
从1-n个数,第i个和第n+1-i个数应是相同的:一个 8 位数字是回文的,当且仅当对于所有的 i(1≤i≤8)从左向右数的第 i 个数字和第 9−i 个数字(即从右向左数的第 i 个数字)是相同的。 ``` Int flag=1; while(s>0){ a[flag]=s%10; s/=10; flag++; } for(i=0;i<=flag/2;i++){ if(a[i]!=a[flag-i]) return false; } ```(2)回文日期
洛谷p2010
更好的题解:找出回文日期看看是否在区间内,可以列举所有月份和其天数,生成回文的年份。闰月0229反过来的9220是闰年。但我的题解是正向思路,判断年月日是否合理,判断回文。
正向思路代码
#include<bits/stdc++.h>
using namespace std;
int hui(int x){
int flag=1,a[15],i=8;
while(x>0){
a[flag]=x%10;
x/=10;
flag++;
}
if(a[1]==0||a[2]>=4||(a[3]>=3&&a[4]==1)||a[4]>=2) return 0;//判断不合理的月份日期
int year=0,month=0,day=0;
while(i>=5){
year=year*10+a[i];
if(i>=7) month=month*10+a[i-4];
if(i>=7) day=day*10+a[i-6];
i--;
}
int d[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},{0,31,29,31,30,31,30,31,31,30,31,30,31}};
int j=0;
if(year%4==0&&year%100!=0||year%400==0) j=1;
if(day>d[j][month]) return 0;
for(int i=1;i<=flag/2;i++){
if(a[i]!=a[flag-i]) return 0;
}return 1;
}
int main(){
int x1,x2,i,ans=0;
cin>>x1>>x2;
for(i=x1;i<=x2;i++){
if(!hui(i)) continue;
ans++;
}
printf("%d",ans);
return 0;
}
5、前缀和
(1)又忘记前缀和咋写了qwq
记个比较的最小值:ans=-2147483647
(2)洛谷子序列p3131
思路:对于每个前缀和,最后一个数为当前i,记录其与7的模。模相同的进行比较,是当前max还是i-之前同一个模的位置的值大。
余数相同的前缀和,作差后可整除7,所含元素即两个前缀和所答i之差。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,i;
cin>>n;
int sum[n+1],max1=0;
sum[0]=0;
for(i=1;i<=n;i++){
cin>>sum[i];
sum[i]+=sum[i-1];
sum[i]%=7;
}
int vis[7];
memset(vis,-1,sizeof(vis));
vis[0]=0;//若能整除7,则所在位置是i-0
for(i=1;i<=n;i++){
int r=sum[i]%7;
if(vis[r]==-1) vis[r]=i;
else{
max1=max(max1,i-vis[r]);
}
}
cout<<max1;
return 0;
}
6、二分
洛谷p1783砍树:这种答案不一定是数组中的某一个数时,不需要二分数组坐标,直接二分每个树的高度即可
点击查看核心代码
while(l<=r){ //左右端点作为结束条件
curr=(l+r)/2;
sum=0;
for(auto &it:w){
if(it>curr) sum+=it-curr;
}
if(sum<m) r=curr-1; //不够就让树再矮一点,在左半部分遍历
else l=curr+1; //超了就让树高一点
}
浙公网安备 33010602011771号