A题:茕茕孑立之影
补充:数据类型及其范围
1. char
有符号char: -128到127, 大致为 -
到
; 无符号char:0到255, 大致为0 到
2. int
有符号int:-2147483648 到 2147483647 , 大致为
到
无符号int:0 到 4294967295,大致为0 到
3.long
有符号long: 大致为
到
; 无符号long: 0 到
4.long long
有符号long long:大致为
到
;无符号long: 0 到
5.float
大致为
到
6.double
大致为
到
思路:
判断数组是否有 1,因为 1 是所有数字的因数,如果有,输出-1;如果没有,找到范围内最大的质数。题目所给的整数范围是,故找到一个更大的质数是 1e9+7
代码:
#include<iostream>
#include<vector>
using namespace std;
int main(){
int res = 1e9 + 7;
int count , k ;//分别是 组数, 该组数的个数
//输入组数
cin >> count;
for(int i = 0; i < count ; i++)
{
//记录输入的一组数的个数
cin >> k;
//记录数组
vector<int> num(k); //分配好k个空间,就不会出现数组越界的问题
bool flag = false;
int max = 0;
for(int j = 0; j < k ;j++){
cin >> num[j];
if(num[j] == 1){
flag = true;
}
}
if(flag){
cout<<"-1"<<endl;
}else{
cout<<res<<endl;
}
}
return 0;
}
B题:一气贯通之刃
思路:
建立一个数组,每个位置则对应一个节点,记录输入路径,在对应位置++,即在位置上记录节点度数。遍历数组,寻找度为1的节点,也就是叶子节点。如果叶子节点超过2个,无法构成简单路径,输出-1; 否则,输出两个叶子节点
代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> degree(n + 1, 0); //定义一个数组,大小为n+1,初始化为0
//记录输入的路径
//每个位置对应一个节点
for (int i = 0; i < n - 1; ++i) {
int u, v;
cin >> u >> v;
degree[u]++; //在对应位置++,即 度数 的改变
degree[v]++;
}
// 寻找度为 1 的节点,也就是叶子节点
vector<int> leaf;
for (int i = 1; i <= n; ++i) {
if (degree[i] == 1) {
leaf.push_back(i);
}
}
// 如果叶子节点超过 2 个,则无法构成简单路径
if (leaf.size() != 2) {
cout << -1 << endl;
}
else {
// 输出两个叶子节点
cout << leaf[0] << " " << leaf[1] << endl;
}
return 0;
}
D题:双生双宿之决
思路:
对于每个数组: 1. 判断个数是否为偶数,否:输出No;2.用unordered_map存储数组,判断是否只有两种键; 3.继续判断每种元素的个数是否相同,通过三个检测,输出Yes;最外层添加一个不符合条件的检测
代码:
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
void ifTwin(pair<int, vector<int>> test)
{
//判断个数是否为偶数
int num = test.first;
if(num % 2 != 0)
{
cout<< "No"<<endl;
return;
}
//个数是偶数,接下来统计是否只有两种键
//先把数组存下来
vector<int> arr = test.second;
unordered_map<int, int> maps;
for(int a : arr)
{
maps[a]++;
}
if(maps.size() == 2)
{
auto it = maps.begin();
int count1 = it->second;
++it;
if(count1 == num / 2)
{
cout << "Yes" << endl;
return;
}
}
//不符合条件
cout << "No" << endl;
}
int main()
{
int count;
cin >> count;
while(count--)
{
int n; //单个数组的大小
cin>> n;
pair<int, vector<int>> test; //存储数组 个数 和 数组内容
vector<int> a(n); //数组内容
for(int i = 0; i < n; i++)
{
cin >> a[i];
}
test = make_pair(n, a); //填充pair
//判断是否是双生数组
ifTwin(test);
}
return 0;
}
补充:pair知识点 & map知识点(unordered_map & order_map )
pair知识点总结
pair是一个模板类,用于将两个不同类型的值组合成一个单元
pair< int, double > p1; //默认初始化:int 为0, double 为0.0
make_pair(20, 2.91); //使用make_pair,可以根据传入的参数自动推导类型
p1.first ; p1.second; //分别访问第一第二个元素
map知识点总结
map基于红黑树(自平衡的二叉搜索树)实现,存储元素的键值对,且键是唯一的,元素会按照键的升序自动排序
头文件: <map>
map< int , string > myMap; //空map
myMap.insert(make_pair(4, "four") ); //使用insert函数插入元素
myMap[5] = "five"; //使用[ ]操作符,如果键不存在,会插入新的键值对;如果已存在,会更新对应的值
查找元素:find函数
//使用find函数: 返回一个迭代器,如果找到则指向该元素,否则指向end( ) auto it = myMap.find(3); if(it != myMap.end() ) { cout << "value of key 3:" << it->second << endl; }
删除元素: erase函数
myMap.erase(3); //根据键删除 auto it = myMap.find(3); if(it != myMap.end() ) { myMap.erase(it); //根据迭代器删除 }
遍历元素:
for( const auto& pair : myMap ) { cout << "Key:" << pair.first << ", Value" << pair.second << endl; }
unordered_map知识点总结
unordered_map,基于哈希表实现,存储的元素是键值对,键是唯一的,但元素不会按照键的顺序排序,而是根据哈希值排序
头文件<unordered_map>
声明、定义、插入、访问、删除元素和map基本相同
G题:井然有序之衡
思路:
对于可以进行任意次操作的题目,要抓住不变的点,这题中为元素之和不变!元素和为排列的和,并且操作时,加1和减1的次数相同。
1.判断元素之和是否为排列和,否,输出-1;
2.将数组自小而大排列,计算对应位置要加/减的数,存在两个数中;
3.判断加和减的数是否相等,如果不等,输出-1, 如果相等,输出减/加其中一个即为操作数
【注意】:计算排列和时候设置的数据类型要为 long long,又因为乘积后的数据类型和原数据类型是一样的,所以代表元素数量的 num 的类型也要是long long
代码:
#include<iostream>
#include<vector>
#include<algorithm>
//数的总和不会改变!!!
using namespace std;
int main()
{
long long num; //数组中元素的数量
cin >> num ;
vector<int> arr(num);
long long sum;
sum = ( (num + 1) * num ) /2; //乘积后的数据类型和原数据类型是一样的,所以num的类型也要是long long
long long count = 0;
for(int i = 0; i< num ;i++)
{
cin >> arr[i];
count += arr[i];
}
if(count != sum)
{
cout<<"-1"<<endl;
}
else{
sort(arr.begin() , arr.end());
//计算对应位置要加/减的数,这两个数相等,就可以,并且就是最小次数
long long plus = 0 , sub = 0 ;
for(int i = 0; i< num ;i++)
{
if(arr[i] == i+1 )
{
continue;
}
else if(arr[i] > i+1)
{
sub += arr[i] - (i + 1);
}
else{
plus += (i + 1) - arr[i];
}
}
if(sub != plus)
{
cout<<"-1"<<endl;
}
else{
cout<<plus<<endl;
}
}
return 0;
}
H题:井然有序之窗
思路:
1. 先将根据左界从小到大进行排序(存储n, r,l三个数)
(1)用优先队列存放->可以存下当前数的区间【有效区间】
(2)移除堆中所有右端点小于当前数字的区间
(3)如果堆为空,输出-1;否则。取出堆顶区间,分配当前数字
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
// 比较函数,先按左端点排序,左端点相同则按右端点排序
bool compare(const pair<pair<int, int>, int>& a, const pair<pair<int, int>, int>& b) {
if (a.first.first == b.first.first) {
return a.first.second < b.first.second;
}
return a.first.first < b.first.first;
}
int main() {
int n;
cin >> n;
vector<pair<pair<int, int>, int>> range(n); // 存放左右范围和原始位置
for (int i = 0; i < n; i++) {
cin >> range[i].first.first >> range[i].first.second;
range[i].second = i; // 记录原始位置
}
// 按左端点从小到大排序
sort(range.begin(), range.end(), compare);
// 小根堆,存储 {右端点, 原始位置}
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> valid;
// 结果数组
vector<int> res(n);
// 标记数字是否已使用
vector<bool> used(n + 1, false);
int index = 0;
for (int num = 1; num <= n; num++) {
// 将左端点小于等于当前数字的区间加入堆中
while (index < n && range[index].first.first <= num) {
valid.push({range[index].first.second, range[index].second});
index++;
}
// 移除堆中所有右端点小于当前数字的区间
while (!valid.empty() && valid.top().first < num) {
valid.pop();
}
// 如果堆为空,说明没有合适的区间可以分配当前数字
if (valid.empty()) {
cout << -1 << endl;
return 0;
}
// 取出堆顶区间,分配当前数字
int pos = valid.top().second;
valid.pop();
res[pos] = num;
used[num] = true;
}
// 输出结果
for (int i = 0; i < n; i++) {
cout << res[i] << " ";
}
cout << endl;
return 0;
}
补充:sort排序 & 小根堆知识点
sort排序:默认比较规则(升序)
头文件: <algorithm>
#include<iostream> #include<vector> #include<algorithm> template<class T> void sort( T first, T last ); int main() { vector<int> nums = {5, 2, 8, 1, 9}; sort(nums.begin(), nums.end()); //升序 for (int num : nums) { cout << num << " "; } cout << endl; return 0; }
自定义规则:自定义一个比较函数
#include <algorithm> #include <vector> #include <iostream> //自定义比较函数,实现降序排序 bool compare(int a, int b){ return a > b; } int main(){ vector<int> nums = {5, 2, 6, 3 }; sort(nums.begin(), nums.end(), compare); for( int num : nums ){ cout << num <<" "; } return 0; }
自定义类型排序,还可以使用lambda表达式; 可以实现对自定义类型的容器(如结构体等)排序