num1:
code:C++
include
using namespace std;
void halfSearch(int* arr, int b, int n)
{
int left = 0;
int right = n - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (arr[mid] == b)
{
cout << "Yes" << endl;
return;
}
else if (arr[mid] > b)
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
cout << "No" << endl;
}
int main()
{
int n;
cin >> n;
int arr[100000];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
int q;
cin >> q;
int brr[100000];
for (int i = 0; i < q; i++)
{
cin >> brr[i];
}
for (int i = 0; i < q; i++)
{
int t = brr[i];
halfSearch(arr, t, n);
}
return 0;
}
代码思路:该代码实现的解题思路是二分查找算法,适用于在有序数组中快速定位目标元素。首先,定义了一个halfSearch函数,该函数接收数组指针、待查找元素和目标数组大小作为参数。在函数内部,通过左右指针界定搜索范围,循环计算中间位置并比较中间元素与目标值。若找到匹配元素,则输出"Yes"并结束搜索;若中间元素大于目标值,则调整右指针缩小搜索范围至左半部分;反之,则调整左指针至右半部分继续搜索。若循环结束仍未找到,则输出"No"。主函数中,读取数组和查询元素,调用halfSearch函数进行查找。
num2:
code:C++
include
include
include
include
include
using namespace std;
int n,c;
long long ans;
map<int,int> a;
int num[200005];
int main()
{
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
a[num[i]]++;
}
for(int i=1;i<=n;i++)
{
ans+=a[num[i]+c];
}
printf("%lld",ans);
return 0;
}
解题思路:首先,通过输入获取数组大小n和一个增量值c,然后读取n个整数存入数组num。利用map容器a高效统计数组中每个数字的出现频次。随后,遍历数组num,对于每个元素num[i],通过查询map中num[i]+c对应的频次,累加到结果ans中。这样,ans最终存储的是数组中每个元素增加c后,在原数组中出现次数的总和。最后,输出ans作为结果。此方法充分利用了map的快速查找特性,有效解决了问题。
num3:
code:C++
include<bits/stdc++.h>
using namespace std;
int n,k,h[100050],w[100050],mid;
int main()
{
cin >> n >> k;
for(int i = 1;i <= n;i++) cin >> h[i] >> w[i];
int l = 1,r = 100000,ans;
while(l < r){
ans = 0;
mid = (l+r+1)/2;
for(int i = 1;i<=n;i++)
ans += (h[i]/mid)*(w[i]/mid);
if(ans >= k) l = mid;
else r = mid-1;
}
cout << l;
return 0;
}
解题思路:首先接收矩形数量n和需覆盖目标数k,以及每个矩形的高度h[i]和宽度w[i]。接着,利用二分查找确定能覆盖至少k个矩形的最小正方形边长。在二分查找过程中,通过计算以当前mid值为边长的正方形能覆盖的矩形数量ans(即每个矩形能被多少个该正方形覆盖后取整相乘求和),来不断调整搜索区间。若ans大于等于k,则尝试缩小正方形边长(即向右移动左边界l),否则增大边长(即向左移动右边界r)。最终,当二分查找结束时,左边界l即为所求的最小正方形边长。
num4:
code:C++
include <bits/stdc++.h>
using namespace std;
const long long inf = 0x3f3f3f3f;
const long long N = 2e5 + 5;
long long n, k;
long long l, r;
long long ans;
long long p[N];
long long m[N];
bool check(long long x)
{
long long need;
need = 0;
for (long long i = 1; i <= n; i++)
{
if (x - p[i] > m[i])
{
return false;
}
need += max(x - p[i], 0ll);
}
if (need <= k)
{
return true;
}
else
{
return false;
}
}
int main()
{
scanf("%lld%lld", &n, &k);
for (long long i = 1; i <= n; i++)
{
scanf("%lld", &p[i]);
}
for (long long i = 1; i <= n; i++)
{
scanf("%lld", &m[i]);
}
l = 1;
r = inf;
for (; l <= r;)
{
long long mid;
mid = (l + r) / 2;
if (check(mid))
{
ans = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
printf("%lld\n", ans);
return 0;
}
解题思路:首先读取任务数n和最大可分配时间k,以及每个任务的基础耗时p[i]和可压缩时间m[i]。定义二分查找的上下界l和r,并在check函数中验证给定时间x是否可行。对于每个任务,若x超出其不可压缩部分,则返回false;否则,累加所需额外时间。若总额外时间不超过k,则返回true。通过二分查找确定最小可行时间ans,最终输出该值。
num5:
code:C++
include<bits/stdc++.h>
using namespace std;
int n,m,a[310],s[310],f[310][310];
void dfs(int k,int t)
{
if(k0) return;
if(k1) {cout<<1<<" "<<t<<endl;return;}
int p=t,s1=a[p];
while(s1<=f[n][m])
{
p--;
s1+=a[p];
}
dfs(k-1,p);
cout<<p+1<<" "<<t<<endl;
}
int main()
{
cin>>m>>n;
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
s[i]=s[i-1]+a[i];
}
memset(f,0x3f,sizeof(f));
for(int i=1;i<=m;i++) f[1][i]=s[i];
for(int i=2;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=j-1;k++) f[i][j]=min(f[i][j],max(f[i-1][k],s[j]-s[k]));
dfs(n,m);
return 0;
}
解题思路:首先,通过输入获取木板切割段数n和木板总段数m,以及各段木板长度。利用前缀和数组快速计算任意区间木板总长。接着,采用动态规划构建二维数组f,其中f[i][j]表示将前j段木板切割成i段的最小最大长度。通过遍历切割点,更新f数组。最后,根据f[n][m]的值,利用深度优先搜索回溯切割方案,打印出每次切割的起始和终止位置(此处终止位置固定为总段数m),从而得到切割成n段的最小最大长度的具体方案。
num6:
code:C++
include
using namespace std;
const int N=1e5+10;
int n,x,h[N],s,j,ans;
int main(){
cin>>n>>x;
for(int i=1;i<n;i++)cin>>h[i];
for(int i=1;i<n;i++){
while(s<2x&&j<n)s+=h[++j];
ans=max(ans,j-i+1);s-=h[i];
}
cout<<ans;
return 0;
}
解题思路:首先读取柱子总数n和需要跨越的宽度x(考虑往返,实际计算中乘以2)。然后,读取n-1个高度差来间接确定每根柱子的高度(假设首柱高度为0)。使用一个循环和滑动窗口技巧,窗口内柱子总高度需达到2x以尝试跨越。在每次窗口滑动时,更新能跨越2*x宽度的最长柱子序列长度。通过不断累加高度并滑动窗口右边界来扩展窗口,同时适时缩小窗口左边界以保持窗口内高度和的有效性,最终得到最长序列长度。

浙公网安备 33010602011771号