CF1669B Triple
题意
给定一个包含 n 元素的数组 a,输出至少出现三次的任何值,如果没有这样的值,则输出 -1。
思路
- 利用map统计每个数出现的次数
- 将第一个出现次数>=3的数输出
- 当没有这样的值输出-1
坑点
- 无
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 +10;
int a[N];
int main()
{
int t;
cin >> t;
while (t -- )
{
int n;
cin >> n;
map<int, int> ma;
int ans = -1;//初值为-1
for (int i = 1; i <= n; i ++ )
{
int x;
cin >> x;
ma[x] ++;
if (ma[x] >= 3)
{
ans = x;
}
}
cout << ans << endl;
}
return 0;
}
总结
签到题
CF1671B Consecutive Points Segment
题意
给出 n 个数 x_1, x_2, …, x_n 保证序列 x 严格递增。对于每个数 x_i,这个数只能选择改变成 x_i - 1或x i +1,当然,也可以不变。问能不能使所有数构成一个连续整数段。可以输出 YES,否则输出 NO。
思路
- 序列包装严格递增的,只需判断首尾的数的差值
- 找到极限的范围确定首尾差的最大值为n+1
- 当在范围内时,可以达到
坑点
- 无
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 +10;
int a[N];
int main()
{
int t;
cin >> t;
while (t -- )
{
int n;
cin >> n;
for (int i = 1; i <= n; i ++ )
{
int x;
cin >> a[i];
}
if (a[n] - a[1] <= n + 1) cout << "YES" << endl;//找到极限的范围确定首尾差的最大值为n+1
else cout << "NO" << endl;
}
return 0;
}
总结
简单思维题
CF680A Bear and Five Cards
题意
给定5个正整数,你可以从中去除2个或3个相同的数。如果没有相同的数,即不能去除。求去除1次后剩余数字的最小和。
思路
- 想要输出的和最小和,那减少的就要最大
- 找到2个或3个相同的数的和最大的减去
坑点
- 无
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 +10;
int a[N];
int main()
{
int sum = 0;//计算初始的和
for (int i = 1; i <= 5; i ++ )
{
cin >> a[i];
sum += a[i];
}
int maxn = 0;
for (int i = 1; i <= 5; i ++ )//找到相同2个数的最大和
{
for (int j = i + 1; j <= 5; j ++ )
{
if (a[i] == a[j])
{
maxn = max(a[i] * 2, maxn);
}
}
}
for (int i = 1; i <= 5; i ++ )//找到3个数的最大和
{
for (int j = i + 1; j <= 5; j ++ )
{
for (int k = j + 1; k <= 5; k ++ )
{
if (a[i] == a[j] && a[j] == a[k])
{
maxn = max(a[i] * 3, maxn);
}
}
}
}
cout << sum - maxn << endl;
return 0;
}
总结
简单模拟题
CF701A Cards
题意
现在有n张卡牌(n为偶数),每张卡牌上都写着一个正整数。有n/2个人要玩这个卡牌游戏,在游戏开始时每个人会得到两张卡牌,每张卡牌只能给一个玩家。 现在让你发卡牌,使每一个人手上的卡片上所写的数字的总和相等。数据保证有发牌的方案符合题目要求。
思路
- 每个人两张牌要使得总和相等,先按从小到大排序
- 利用两个指针分别指向首尾,依次向中间推进
- 因为需要输出对应卡片的位置可以利用结构体保存对应数字和位置号
坑点
- 数据保证有发牌的方案符合题目要求
代码
#include<bits/stdc++.h>
using namespace std;
struct name{
int xu;//位置号
int s;//对应数字
}a[110];
bool cmp(name x,name y)//按从小到大排序
{
if(x.s==y.s)
{
return x.xu<y.xu;
}
else{
return x.s<y.s;
}
}
int main()
{
int n;
cin>>n;
int b[1110];
for(int i=1;i<=n;i++)
{
cin>>a[i].s;
a[i].xu=i;//赋值每个位置号
}
sort(a+1,a+1+n,cmp);
int l=1,r=n;//利用两个指针
while(l<r)
{
cout<<a[l].xu<<" "<<a[r].xu<<endl;
l++;
r--;
}
return 0;
}
总结
结构体,贪心,需要注意细节
CF1623C Balanced Stone Heaps
题意
你有 nn 堆石子,其中第 ii 堆里面有 h_i 粒石子。你需要从第 3 堆石子开始从前往后进行操作。设当前为第 i 堆石子,你可以选择一个在 [0,h_i/3]的整数 d,从第 ii堆石子中取出 3d粒石子,然后往第 i-1堆石子里放入 d 粒石子,往第 i-2 堆石子里放入 2d 粒石子。
你需要通过合理设计操作方案,使得数量最少的一堆石子的数量最大。请求出这个最大值。
思路
- 利用二分先确定这个最小值
- 从后往前遍历当大于最小值时可以将当前的分给前两个位置,最后判断最初1,2位置是否满足
坑点
- d的范围在[0,hi/3]之间
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 +10;
int a[N], b[N];
int n;
bool check(int x)
{
for (int i = 1 ; i <= n; i ++ ) b[i] = a[i];//b为每堆石子的变化,a为初始的石子
for (int i = n; i >= 3; i -- )
{
if (b[i] < x) return false;
int d=(b[i]-x)/3;
d = min(d, a[i]/3);//d的范围在[0,hi/3]之间
b[i-1] += d;
b[i-2] += 2*d;
}
if(b[1]>=x&&b[2]>=x) return true;//当1,2位置的石子满足条件
else return false;
}
int main()
{
int t;
cin >> t;
while (t -- )
{
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i];
}
int l = 0, r = 0x3f3f3f3f;
while (l < r)//利用二分寻找最大值
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout << l << endl;
}
return 0;
}
总结
二分答案题