第三天训练小结

今天听了题解还有问了别的大佬赶在时间截止之前伪ak了一把wwwww

今天的内容主要是二分

int binarySearch(int[] nums, int target) {

    int left = 0;

    int right = nums.length - 1; // 注意

 

    while(left <= right) { // 注意

        int mid = (right + left) / 2;

        if(nums[mid] == target)

            return mid;

        else if (nums[mid] < target)

            left = mid + 1; // 注意

        else if (nums[mid] > target)

            right = mid - 1; // 注意

        }

    return -1;

}

以上是基本的二分框架,对于二分的算法问题注意点在于循环判断的点(何时退出),以及左右边界的移动,根据循环条件而判断

https://www.cnblogs.com/kyoner/p/11080078.html(大佬的二分详解,讲的很详细,有空自己再看看)

 

题型一:对已有数据进行查找操作(为了使时间复杂度更小采用二分的方法)

 

B - Dating with girls(1)

 Everyone in the HDU knows that the number of boys is larger than the number of girls. But now, every boy wants to date with pretty girls. The girls like to date with the boys with higher IQ. In order to test the boys ' IQ, The girls make a problem, and the boys who can solve the problem
correctly and cost less time can date with them.
The problem is that : give you n positive integers and an integer k. You need to calculate how many different solutions the equation x + y = k has . x and y must be among the given n integers. Two solutions are different if x0 != x1 or y0 != y1.
Now smart Acmers, solving the problem as soon as possible. So you can dating with pretty girls. How wonderful!(hdu-2578)

思路主要就是先去把一个序列给排序一下,然后再在这个序列里面找数字(主要注意是否有数字重复的问题并且解决)

 

 

题型二:遍历数据,其中数据是所求的答案(浮点数)

 

D - Pie

 问题主要是讲分蛋糕,一个人有多块蛋糕分给别人但是被分到的人的蛋糕必须来自同一块蛋糕上(二分,求最大蛋糕的体积)

 

#include <iostream>

 

#include <cmath>

 

#include <cstdio>

 

#include <string.h>

 

#include <algorithm>

 

using namespace std;

 

#define pi acos(-1)

 

int n,f;

 

double a[10010];

 

bool check(double x)

 

{

 

    int num=0;

 

    for(int i=0;i<=n-1;i++)

 

    {

 

       num+=(int)(a[i]*a[i]*pi/x);

 

    }

 

    if(num>=f+1) return 1;//包括自己是f+1个人

 

    return 0;

 

}

 

int main()

 

{

 

    int t;

 

    scanf("%d",&t);

 

    while(t--)

 

    {

 

       scanf("%d%d",&n,&f);

 

       for(int i=0;i<=n-1;i++)

 

       {

 

           scanf("%lf",&a[i]);

 

       }

 

       sort(a,a+n);

 

       double l=0,r=pi*a[n-1]*a[n-1];//r为最大蛋糕的体积

 

       double ans=0;

 

       while(l+(1e-6)<r)

 

       {

 

           double mid=(l+r)/2;//mid表示每个人可以分到的蛋糕的体积

 

           if(check(mid))

 

           {

 

              l=mid;

 

              ans=mid;

 

           }

 

           else

 

           {

 

              r=mid;

 

           }

 

       }

 

       printf("%.4f\n",ans);

 

    }

 

    return 0;

 

}

 

贴一个自己的代码)

 

题型三:求一个最大值(比如两个固定点的最大值,炸弹给时间问题)

思路一般都是求什么然后去设它,最后用二分不断到它的值

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
long long a[100010];
int t,n;
long long sum=0;//总共需要点的时间
long long time(int x)
{
sum=0;
for(int i=1;i<=n;i++)
{
if(a[i]<x)
{
sum+=(x-a[i]);
}
}
return sum;
}
int main()
{
scanf("%d",&t);
for(int u=1;u<=t;u++)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
//printf("%lld ",a[i]);
}
sort(a+1,a+n+1);
long long l=0,r=2000000000;
long long mid;
while(l<=r)
{
mid=(l+r)/2;
if(time(mid)<=mid)//要救的时间比给定时间小
{
l=mid+1;
}
else
{
r=mid-1;
}
}
printf("Case #%d: %d\n",u,l);
}
return 0;
}

(这是ccpc绵阳站的G - Defuse the Bombs代码)思路则是拯救炸弹的时间然后不断逼近

 

E - River Hopscotch

 POJ - 3258 (这一题思路更直接,直接求之间的距离然后求可以去掉的点,注意一下边界问题)

#include <iostream>

#include <cstdio>

#include <cmath>

#include <algorithm>

using namespace std;

int a[50010];

int main()

{

    int lenth,n,m;

    scanf("%d %d %d",&lenth,&n,&m);

    for(int i=1;i<=n;i++)

    {

       scanf("%d",&a[i]);

    }

    sort(a+1,a+n+1);

    int l=0,r=lenth;

    int mid,result;

    while(l<=r)

    {

       mid=(r+l)/2;//二分距离

       int temp=0;//刚开始从河的0端过来,记得考虑末尾

       int sum=0;

       for(int i=1;i<=n;i++)

       {

           if(a[i]-temp<mid)//可以跳过的距离

           {

              continue;

           }

           else

           {

              sum++;

              temp=a[i];

              if(lenth-a[i]<mid)

              {

                  break;

              }

           }

       }

       if(sum>=n-m)//判断用了的石头个数

       {

           l=mid+1;

       } //次数多,距离小,距离需要偏大

       else

       {

           r=mid-1;

       }

    }

    cout<<l-1<<endl;

    return 0;

}

----------------------------------------------------------------------------------------------------

明天继续加油!!!

 

 

posted @ 2021-01-22 19:13  Treasure-  阅读(41)  评论(0)    收藏  举报