5.22ACM周末总结

1.利用lower_bound和upper_bound在多个数组中查找多个数组中某个元素
lower_bound(数组的初始位置,数组的末尾位置,要查找的数字):
从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标
upper_bound (数组的初始位置,数组的末尾位置,要查找的数字)
从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
binary_search (arr[],arr[]+size , indx)
判断某个元素是否出现(排好序,递增)
D-D:

for(int i=1; i<=n; i++) scanf("%d %d %d %d",&A[i],&B[i],&C[i],&D[i]);
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++) S[++cnt] = A[i] + B[j];
		sort(S + 1, S + cnt + 1);	
		long long Ans = 0;
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++)
				Ans += upper_bound(S + 1,S + cnt + 1,-C[i]-D[j]) - lower_bound(S + 1,S + cnt + 1, -C[i]-D[j]) ;
		printf("%lld\n",Ans);

2.二分的分类
(1)对一个区间中一个数的查找:能在一个折半的区间中找到index就结束,不行就根据index的大小更新区间,但前提一定是单调递增的区间

int WA(int[]nums,int index,int l,int r)
{
while(l<=r)//index是要查找的数
{
int mid=(l+r)/2;
if(a[mid]==index)
 return mid;
else if(a[mid]>index)
  r=mid-1;
else
  l=mid+1;  
}
}

(2)最值类(最大值最小/最小值最大)

while(l<=r)//放主函数中
{
int mid=(l+r)/2;
if(judge(mid))
  {  
     res=mid;
     l=mid+1;
  }
else r=mid-1;
}
....
.....
......
cout<<res;

G-G:
给你你在N个月中每月的花费,你想将N个月分成M组,每组的月份是连续的,同一组的花费加起来,求所有分组中最高花费的最低值
先确定l和r的值,首先明确它要折半搜索的是一组花费的花费总和,r应该是N个月的总和花费,l应该是这N个月中最大的花费
judge函数:遍历各个月份,将花费不大于mid的月份归为一个组,统计在当前mid情况下能分成几组:如果组数小于M,这说明mid取大了,那就取半

#include<iostream>
#include<cstdio>
#include<cstring>
#define MMAX 100003
using namespace std;
int day[MMAX],N,M;
int judge(int mid)
{
    int k=1;
    int sum=0;
    for(int i=0; i<N; i++)
    {
        if(sum+day[i]>mid)
        {
            sum=day[i];
            k++;
            continue;
        }
        sum+=day[i];
 
    }
    return k;
 
}
int main()
{
    while(~scanf("%d%d",&N,&M))
    {
        int Max=0;
        int sum=0;
        for(int i=0; i<N; i++)
        {
            scanf("%d",&day[i]);
            Max=max(Max,day[i]);
            sum+=day[i];
        }
        int low=Max,high=sum,mid;
        while(low<high)
        {
            mid=(low+high)/2;
            if(judge(mid)<=M){
                high=mid-1;
            }
            else low=mid+1;
        }
        cout<<low<<endl;
 
    }
    return 0;
}

H-H(最小的最大):石子过河

#include <iostream>
#include <algorithm>
using namespace std;
const int k=2e5+10;
int a[k];

long long l,n,m,i;
bool judge(long long mid)
{
    long long start=0,res=0;
    for( i=1; i<=n; i++)
    {
        if(a[i]-start<mid)
        {
            res++;
        }
        else
        {
            start=a[i];
        }

    }
    if(res<=m) return 1;
    else return 0;

}
int main()
{
    cin>>l>>n>>m;
    for(i=1; i<=n; i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+1+n);

    long long left,right,mid,re;
    left=0;
    right=l;
    while(left<=right)
    {
        mid=(left+right)/2;
        if(judge(mid))
        {

            left=mid+1;
        }
        else
        {
            right=mid-1;
        }
    }
    cout<<right<<endl;
    return 0;
}

结论:最大的最小,输出是left/low,带等于号放在right;
最小的最大,输出是right/high,带等于号放在left;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉梦昂志️

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值