蓝桥杯训练day2
day2
- 1.二分
- (1)789. 数的范围
- (2)四平方和
- (1)哈希表做法
- (2)二分做法
- (3)1227. 分巧克力
- (4)113. 特殊排序
- (5)1460. 我在哪?
- 2.双指针
- (1)1238. 日志统计
- (2)1240. 完全二叉树的权值
- (3)字符串删减
- (4)799. 最长连续不重复子序列
- (5)800. 数组元素的目标和
- (6)判断子序列
1.二分
(1)789. 数的范围
思路:
需要找到一个值的区间。比如1 2 2 3 4 5 找2的区间,即[1,2]
因为数组是有序的,所以可以使用二分查找。
(1)使用二分查找找左边界
(2)使用二分查找找右边界
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;const int N=100010;int n,q;int a[N];int find1(int t) //找到当前查找数的区间左边界
{int res=-1;int l=0,r=n-1;int mid=(l+r)>>1;while(l<=r){mid=(l+r)>>1;if(a[mid]>t)r=mid-1;else if(a[mid]<t)l=mid+1;else{res=mid;r=mid-1;}}return res;
}int find2(int t)
{int res=-1;int l=0,r=n-1;int mid=(l+r)>>1;while(l<=r){mid=(l+r)>>1;if(a[mid]>t)r=mid-1;else if(a[mid]<t)l=mid+1;else{res=mid;l=mid+1;}}return res;
}int main()
{cin>>n>>q;for(int i=0;i<n;i++)cin>>a[i];while(q--){int t;cin>>t;cout<<find1(t)<<" "<<find2(t)<<endl;}return 0;
}
(2)四平方和
经典哈希问题,二分问题。
第一步:先找出两个数的平方和的所有组合(不超过n)
第二步:n减去两个数的平方和,剩下的数看是否在第一步预处理过。
为什么可以保证字典序最小呢:
(1)在第二步中,a,b是从小到大枚举的,且可以保证a<=b恒成立,为什么?如果a>b成立,那么把a,b置换一下,一样成立。然后第一次成立就会结束,所以不可能遇到a>b的情况
(2)C[k],D[k]也是一样的道理。在第一步就可以证明。
(1)哈希表做法
#include<iostream>
#include<cstring>
using namespace std;const int N=5000010;int C[N],D[N];int n;int main()
{cin>>n;memset(C,-1,sizeof C);//第一步:将所有两个数的组合都算出来for(int a=0;a*a<=n;a++){for(int b=a;b*b+a*a<=n;b++){int k=a*a+b*b;if(C[k]==-1){C[k]=a,D[k]=b;}}}//第二步,将n减去ab两个数的组合,剩下的看之前是否存储,如果有,直接输出。而且一定满足字典序最小for(int a=0;a*a<=n;a++){for(int b=a;b*b+a*a<=n;b++){int k=n-a*a-b*b;if(C[k]!=-1){cout<<a<<" "<<b<<" "<<C[k]<<" "<<D[k]<<endl;return 0;}}}return 0;}
(2)二分做法
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;const int N=5000010;struct Sum
{int s,c,d; //s表示a*a+b*bbool operator<(const Sum &t)const //为什么重载小于号{if(s!=t.s)return s<t.s;if(c!=t.c)return c<t.c;return d<t.d;}
}sum[N];int n;
int m;int main()
{cin>>n;for(int c=0;c*c<=n;c++)for(int d=c;c*c+d*d<=n;d++)sum[m++]={c*c+d*d,c,d};sort(sum,sum+m);for(int a=0;a*a<=n;a++){for(int b=a;b*b+a*a<=n;b++){int t=n-a*a-b*b;int l=0,r=m-1;while(l<r){int mid=(l+r)>>1;if(t<=sum[mid].s)r=mid;elsel=mid+1;}if(t==sum[l].s) //或者t==sum[r].s 因为最终l==r{cout<<a<<" "<<b<<" "<<sum[r].c<<" "<<sum[r].d<<endl;return 0;}}}return 0;
}
(3)1227. 分巧克力
还以为有什么技巧咧,看半天。。就一个暴力做法。。。二分正方形的边长
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;const int N=1e5+10;int n,k;int H[N],W[N];bool check(int t)
{long long res=0;for(int i=0;i<n;i++){res+=H[i]/t*(W[i]/t);if(res>=k)return true;}return false;
}
int main()
{cin>>n>>k;for(int i=0;i<n;i++)cin>>H[i]>>W[i];int l=1,r=1e5;while(l<r){int mid=(l+r+1)>>1; //为什么+1,这是因为避免死循环,为什么会死循环。博客里面有相关文章if(check(mid))l=mid;elser=mid-1;}cout<<l<<endl;return 0;
}
(4)113. 特殊排序
难难难!!!
关键在于对“无序二分”的合理证明。
二分一定是有道理才能的。光看难懂,要仔细体会。不会的小伙伴可以私信,我这个菜鸟看了30分钟才看懂😢
// Forward declaration of compare API.
// bool compare(int a, int b);
// return bool means whether a is less than b.class Solution
{
public:vector<int> specialSort(int N) {vector<int>res;res.push_back(1); //使用插入排序+二分,res就是排序主体,开始数组只有1个元素,当然是有序的for(int i=2;i<=N;i++){//这里规定找到第一个小于i的位置,且该位置后面一个数大于i。然后让i插入到第一个小于i的位置后面的一个位置//这是合理的.//如果当前数x比i小,那么i一定可以在x右边放下:如果x右边所有的数都比i小,那么i放在最右端//如果x右边有一个数比i大,那么i放在该数位置,该数以及后面的数右移。//所以找到第一个小于i的数且后面大于i的数(也可以没有)即可//注意,如果没有小于i的数,那么i放在第一位int l=0,r=res.size()-1;while(l<r){int mid=(l+r+1)>>1;if(compare(res[mid],i))l=mid; //如果mid小于i,那么i一定可以插入到mid后面(也可能可以插入到mid左边)elser=mid-1;}res.push_back(i);//最后l==r,[l,l+1]分别表示小于i,大于i的数for(int j=res.size()-2;j>r;j--)swap(res[j],res[j+1]);//判断r是否合理。如果i比res[r]小,则和我们假设不符合,那么就只有一种可能,i比所有数都小,自然也比第一个数小,这个时候i只可能是第二个数,那么和第一个数交换位置即可if(compare(i,res[r]))swap(res[r],res[r+1]);//也可写 if(compare(res[r+1],res[r])swap(res[r],res[r+1]);}return res;}
};
(5)1460. 我在哪?
这道题数据很小,可以直接暴力解决。直接枚举所有连续的字符串的组合,找到唯一的那一个,记录下长度即可,非常简单。但是标签是二分,待我去看看题解如何解答。。
//目的找到一个最小长度且没有重复的字符串#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;const int N=110;int n;
char str[N];
int res;int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>str[i];unordered_map<string,int>Hash;for(int len=1;len<=n;len++) //枚举长度{int cnt=0;for(int start=1;start+len-1<=n;start++) //枚举起点{string temp="";for(int j=start;j<=start+len-1;j++) //累计枚举区间的字符串temp+=str[j];Hash[temp]++;if(Hash[temp]==1)cnt++;}if(cnt==n-len+1) //说明该长度的所有组合都是第一次出现{cout<<len<<endl;return 0;}}return}
二分还真可以做,需要字符串哈希的我知识,也可以直接用stl
先贴一个代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>using namespace std;int n;
string str;
unordered_set<string> S;bool check(int mid)
{S.clear();for (int i = 0; i + mid - 1 < n; i ++ ){string s = str.substr(i, mid);if (S.count(s)) return false;S.insert(s);}return true;
}int main()
{cin >> n >> str;int l = 1, r = n;while (l < r){int mid = l + r >> 1;if (check(mid)) r = mid;else l = mid + 1;}cout << r << endl;return 0;
}
2.双指针
(1)1238. 日志统计
双指针的习题:
思路:先给排序,排序规则:帖子编号从小到大,如果帖子编号一样,则给时间从小到大排序
然后用一个l,r指向一个帖子的区间,判断该帖子是否满足要求,然后判断下一个帖子
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;const int N = 1e5 + 10;int n, d, k;int res[N];
int rc=0;struct node
{int id;int ts;node():id(0),ts(0){}
};node a[N];bool cmp(node &a, node& b)
{if (a.id == b.id)return a.ts < b.ts;return a.id<b.id;
}int main()
{cin >> n >> d >> k;for (int i = 0; i < n; i++)cin >> a[i].ts >> a[i].id;sort(a, a + n, cmp);// for (int i = 0; i < n; i++)// {// cout << a[i].ts << " " << a[i].id << endl;// }//对帖子一个个进行判断//一个指针指向起始时间,一个指向末尾时间int l=0,r=0; //l,r分别是一个帖子的不同时间(开始时间和截至时间)int cnt=0;while(l<n&&r<n){if(a[l].id==a[r].id) //帖子一样{if(a[r].ts-a[l].ts+1<=d){cnt++;r++;}else{l++;cnt--;}if(cnt==k){res[rc++]=a[l].id;cnt=0;int t=a[l].id;while(a[l].id==t)l++;r=l;}}else{l=r;cnt=0;}}for(int i=0;i<rc;i++)cout<<res[i]<<endl;return 0;
}
(2)1240. 完全二叉树的权值
思路:
先将每一层的权值算出来,然后用一个变量res记录最大值。因为层数从小到大遍历,遇到大的才更新,所以可以保证第一次遇到的最大值层数最小。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;typedef long long LL;const int N = 100010;int n;
int a[N];int main()
{scanf("%d", &n);for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);LL maxs = -1e18;int depth = 0;for (int d = 1, i = 1; i <= n; i *= 2, d ++ ){LL s = 0;for (int j = i; j < i + (1 << d - 1) && j <= n; j ++ )s += a[j];cout<<s<<endl;if (s > maxs){maxs = s;depth = d;}}printf("%d\n", depth);return 0;
}
贴上自己第一次写的代码,说明功底还不够
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+10;ll a[N];
ll deep[N]; //deep[i]=j表示深度为i的那一层的权值之和为j
int dc=1;int n;struct node
{int d;ll cnt;
};node b[N];bool cmp(node &a,node &b)
{if(a.cnt==b.cnt)return a.d<b.d;return a.cnt>b.cnt;}void count() //计算每一层的个数
{int start=0; //一层的开始int k=1; //一层的个数while(start<=n) //计算每一层的权值{ for(int i=start;i<min(n,start+k);i++){deep[dc]+=a[i];}start+=k;k*=2;dc++;}
}int main()
{cin>>n;for(int i=0;i<n;i++)cin>>a[i];count();// for(int i=1;i<dc;i++)// cout<<deep[i]<<" ";//将每一层的权值之和都算出来就简单了,想怎么做都可以,用一个结构体存下层数和大小,先按大小排序,//cout<<dc<<endl;//如果大小一样,就按照层数排序for(int i=1;i<dc;i++){b[i].d=i;b[i].cnt=deep[i];}sort(b+1,b+dc,cmp);cout<<b[1].d<<endl;return 0;}
(3)字符串删减
思路:
准备工作:
(1)变量ok,遇到x置为true,否则false
(2)left,right指针,left指向第一个遇到的x,right指向最后一个遇到的x
一次遍历即可
#include<iostream>
#include<cstring>using namespace std;const int N=110;int n;
char a[N];
int res=0;int main()
{cin>>n;for(int i=0;i<n;i++)cin>>a[i];int l,r;int sum=0;bool ok=false;for(int i=0;i<n;i++){if(a[i]=='x'){if(!ok){l=r=i;sum=1;ok=true;}else{r++;sum++;}}else{ok=false;if(sum>=3){res+=sum-2;sum=0;}}}if(sum>=3)res+=sum-2;cout<<res<<endl;return 0;}
(4)799. 最长连续不重复子序列
用一个哈希表实时记录出现的元素次数,两个指针指向前后一次遍历即可
#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;const int N = 1e5 + 10;int a[N];
int n;int res = 0;int main()
{cin >> n;for (int i = 0; i < n; i++)cin >> a[i];unordered_map<int, int>Hash; //哈希表int l = 0, r = 0;while (l < n && r < n){if (Hash.count(a[r]) == 0 || Hash[a[r]] == 0){Hash[a[r]] = 1;r++;}else{res = max(res, r - l);while (l < n && a[l] != a[r]){Hash[a[l]] = 0;l++;}Hash[a[l]] = 0;l++;}}res=max(res,r-l); //最后一次判断,以免漏掉cout << res;return 0;}
(5)800. 数组元素的目标和
经典双指针,一前一后。用反证法证明不会漏过答案
#include<iostream>
#include<cstring>
using namespace std;const int N=1e5+10;int a[N];
int b[N];int n,m;
int k;int main()
{cin>>n>>m>>k;for(int i=1;i<=n;i++)cin>>a[i];for(int j=1;j<=m;j++)cin>>b[j];int l=1,r=m;bool ok=true;while(ok){if(a[l]+b[r]>k)r--;else if(a[l]+b[r]<k)l++;elseok=false;}cout<<l-1<<" "<<r-1<<endl;return 0;}
(6)判断子序列
#include<iostream>
#include<cstring>
using namespace std;const int N=1e5+10;int n,m;int a[N],b[N];int main()
{cin>>n>>m;for(int i=0;i<n;i++)cin>>a[i];for(int i=0;i<m;i++)cin>>b[i];int i,j;for(i=0,j=0;i<n&&j<m;j++){if(a[i]==b[j])i++;}if(i==n)cout<<"Yes";else cout<<"No";return 0;
}
相关文章:

蓝桥杯训练day2
day21.二分(1)789. 数的范围(2)四平方和(1)哈希表做法(2)二分做法(3)1227. 分巧克力(4)113. 特殊排序(5)1460. 我在哪?2.双指针(1)1238. 日志统计(2)1240. 完全二叉树的权值(3&#…...

为什么99%的程序员都做不好SQL优化?
连接层 最上层是一些客户端和链接服务,包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于 TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程 池的概念,为通过认证安全接入的客户端提供线程。同样…...

Jenkins最新版安装调试
清理旧的jenkins: find / -name jenkins* 一项一项的清理:rm -rf /var/log/jenkins* 下载最新版jenkins镜像:jenkins-redhat-stable安装包下载_开源镜像站-阿里云 上传到服务器: 安装命令: yum install -y jenkins…...
简略说一下go的sync.RWMutex锁
在简略的说之前,首先要对RW锁的结构有一个大致的了解 type RWMutex struct {w Mutex // 写锁互斥锁,只锁写锁,和读锁无关writerSem uint32 // sema锁--用于“写协程”排队等待readerSem uint32 // sema锁--用于“读协程”排队…...
软考马上要报名了,出现这些问题怎么办?
目前,四川、山东、山西、辽宁、河北等地已经率先发布了2023年上半年软考报名通知。 四川:2023年3月13日-4月4日 山东:2023年3月17日9:00-4月3日16:00 山西:2023年3月14日9:00-3月28日11:00 辽宁:2023年3月14日8:30…...
单链表(增删查改)
目录一、什么是单链表?二、单链表的增删查改2.1 结构体变量的声明2.2 申请新结点2.2 链表的头插2.3 链表的尾插2.4 链表的头删2.5 链表的尾删2.6 链表的查找2.7 链表的任意位置后面插入2.8 链表的任意位置后面删除2.9 链表的销毁2.10 链表的打印三、代码汇总3.1 SLi…...

端口复用(bind error: Address already in use 问题)
欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 端口复用专栏:《Linux从小白到大神》《网络编程》 在前面讲解TCP状态转换中提到过一个2MSL…...

数字化引领乡村振兴,VR全景助力数字乡村建设
一、数字乡村建设加速经济发展随着数字化建设的推进,数字化农业产业正在成为农业产业发展的主导力量,因此数字化技术赋予农业产业竞争力的能力不可小觑。数字化乡村建设背景下,数字化信息技术将全面改造升级农村产业,从农业、养殖…...

【数据结构入门】-链表之双向循环链表
个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【数据结构初阶(C实现)】 文章目录链表初始化打印链表尾插尾删新建一个节点头插头删查找在pos之前插入*删除pos位…...

Jenkins自动化部署入门
Jenkins自动化部署入门 一、简介 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。 Jenkins自动化部署实现原理 二、Jenkins部…...

Springboot 读取模板excel信息内容并发送邮件, 并不是你想想中的那么简单
Springboot 读取模板excel信息内容并发送邮件 背景技术选型搭建过程数据加密隐藏问题暴露背景追溯解决背景 在我们日常开发中, 会遇到这样一种场景, 就是读取表格中的数据, 并将数据以附件的形式通过邮箱发送到表格中的每个人 即: excel 读取 excel 写入 发送邮件(携带附件), 例…...

蓝桥杯真题31日冲刺 |第一天
蓝桥杯真题31日冲刺 |第一天 一:完全平方数 题目:[链接](完全平方数 - 蓝桥云课 (lanqiao.cn)) 思路: 将 每个 完全平方数都 消掉,剩下的就是 不能构成平方的数 以12 为例: 所以 12 只要再 乘个三 即可满足 代…...

STM32开发(18)----CubeMX配置RTC
CubeMX配置RTC前言一、什么是RTC?RTC时钟源RTC备份域二、实验过程1.CubeMX配置2.代码实现3.实验结果总结前言 本章介绍使用STM32CubeMX对RTC进行配置的方法,RTC的原理、概念和特点,配置各个步骤的功能,并通过实验方式验证。 一、…...

Qt 单例模式第一次尝试
文章目录摘要单例模式如何使用Qt 的属性系统总结关键字: Qt、 单例、 的、 Q_GLOBAL_STATIC、 女神节摘要 世界上第一位电脑程序设计师是名女性:Ada Lovelace (1815-1852)是一位英国数学家兼作家,她是第一位主张计算机不只可以用来算数的人…...

C语言--一维数组
数组概念 数组:是一种构造数据类型,用以处理批量的同种类型的数据。 主要特点:数据量大 ,类型相同 一维数组的定义 语法: 类型说明符 数组名[整型常量表达式]; 注意: 方括号里面的内容用于指…...

DataGear 4.5.1 发布,数据可视化分析平台
DataGear 4.5.1 发布,严重 BUG 修复,具体更新内容如下: 修复:修复SQL数据集对于DB2、SQLite等数据源预览时会报错的BUG;修复:修复系统对于MySQL、MariaDB等数据源中无符号数值类型有时报错的BUG࿱…...

Springboot——@valid 做字段校验和自定义注解
文章目录前言注意实现测试环境验证自带的注解自定义valid注解自定义注解和处理类创建参数接收类,并增加字段注解接口中使用自测环节正常测试异常测试自定义全局异常监听扩展递归参数下valid不识别的坑前言 再项目开发中,针对前端传递的参数信息…...
c语言基础练习题详解
💞💞 1.C语言程序的基本单位是(C)。 A.程序行 B. 语句 C. 函数 D.字符 💞💞 2.已知各变量的类型说明如下: int m6,n,a,b; unsigned long w8;…...

C语言设计模式:实现简单工厂模式和工程创建
目录 一,设计模式概念引入 ① 什么是设计模式 ② 什么是类和对象 ③ 什么是工厂模式 二,C语言工厂模式的实现 ① 普通类和对象的代码实现 ② 工厂模式代码实现 ● cat.c ● dog.c ● person.c ● animal.h ● mainpro.c ● 完善mainpro.c …...
3.6日报
今天进行3.0信号整理工作 做官网后台技术文档 了解grpc gRPC是rpc框架中的一种,是rpc中的大哥 是一个高性能,开源和通用的RPC框架,基于Protobuf序列化协议开发,且支持众多开发语言。 面向服务端和协议端,基于http…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...