二分算法周结

这周练习了二分算法的题目,二分算法属于分治算法的一种,可以用于快速遍历元素,可以将问题规模变小等等,分治算法就是分而治之,就是将较大规模的问题分解成较小规模的问题,二分算法也是,在我们 面对一种问题的时候,将他分解成了两个问题,这样大问题就被分解成了两个小问题,然后这两个小问题可以继续分解成规模更小的问题。这大概就是二分算法的含义。

二分算法如果让我们通俗一点去理解的话可以打个比方,比如我们查字典,并不是那种按照第一页目录那样去找,而是直接翻书找字母那种,好比我要查的词开头单词是s,那么第一步我把书从中间放开,发现是字母是o,那么s在o后面,那么o前一半的书我就可以不管了,然后我再在o之后的部分的中间将这本书分开,看见是字母u那么判断,s在u之前,那么u之后的部分我就不需要考虑了,我下面再在o和u的中间把树翻开,这样找到了s,所谓二分就是不断地将问题规模变小,直到达成自己的目的为止。就是那种不达目的据不罢休的那种感觉。

如果是用二分法找某一个数,那么二分法的模板是下面这样

left=1;//左边界
right=n;//右边界
while(left<=right)
{
    mid=(left+right)/2;
    if(a[mid]<=x)
        left=mid+1;
    else right=mid-1;
}
//不断变更左右边界,模拟二分过程

二分算法还可以用来进行快速排序,速度非常快,当时缺点就是不太稳定,模板如下

void qsort(int le,int ri)
{
    int i=le,j=ri;
    int mid=a[(le+ri)/2];
    while(i<=j)
    {
        while(a[i]>mid) i++;
        while(a[j]<mid) j--;
        if(i<=j)
        {
            swap(a[i],a[j]);
            i++;
            j--;
        }
    }
    if(le<j) qsort(le,j);
    if(i<ri) qsort(i,ri);
}

至于二分算法用来将问题规模变小的那种方法就可以通过第一种模板,就是找某个数的模板上加以演化即可

下面附上几道我最近做的vj的二分算法的题目

A new e-mail service "Berlandesk" is going to be opened in Berland in the near future. The site administration wants to launch their project as soon as possible, that's why they ask you to help. You're suggested to implement the prototype of site registration system. The system should work on the following principle.

Each time a new user wants to register, he sends to the system a request with his name. If such a namedoes not exist in the system database, it is inserted into the database, and the user gets the response OK, confirming the successful registration. If the name already exists in the system database, the system makes up a new user name, sends it to the user as a prompt and also inserts the prompt into the database. The new name is formed by the following rule. Numbers, starting with 1, are appended one after another to name (name1, name2, ...), among these numbers the least i is found so that name idoes not yet exist in the database.

Input

The first line contains number n (1 ≤ n ≤ 105). The following n lines contain the requests to the system. Each request is a non-empty line, and consists of not more than 32 characters, which are all lowercase Latin letters.

Output

Print n lines, which are system responses to the requests: OK in case of successful registration, or a prompt with a new name, if the requested name is already taken.

Examples

Input

4
abacaba
acaba
abacaba
acab

Output

OK
OK
abacaba1
OK

Input

6
first
first
second
second
third
third

Output

OK
first1
OK
second1
OK
third1

这个题目后来查阅了一下资料知道是cf一道c题,其实做出来还挺惊喜的,因为除了愚人节的比赛,还有有一场比赛我能ac到c题,所以以后还是多多挑战一下,其实有的时候不行不是真的不行,只是我觉得我不行 ,下次还是要敢做

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
long i,n,count=0,a[100000]={0},flag;
char str[50],ch[100000][50];
main()
{

    cin>>n;
    while(n--)
    {
        flag=0;
        cin>>str;
        for(i=0;i<=count;i++)
            if(strcmp(str,ch[i])==0)
            {
                a[i]++;
                flag=1;
                break;
            }
        if(flag==0)
        {
            strcpy(ch[count],str);
            count++;
            cout<<"OK"<<endl;
        }
        else{
            cout<<str<<a[i]<<endl;
        }
    }
}

The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .

Input

The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 2 28 ) that belong respectively to A, B, C and D .

Output

For each input file, your program has to write the number quadruplets whose sum is zero.

Sample Input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample Output

5

Hint

Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30). 

这个题目的话就是,先分别求出前两列后两列的所有的和,然后对后两列的和进行排序,对后两列进行二分查找看有多少种情况即可

#include<iostream>
#include<cstdio>

#include<cstring>
#include<algorithm>
using namespace std;
int a[5010][6];
int s1[16000100];
int s2[16000100];
int n,k2=1;
int sum;
void judge(int a1)
{
    int st=1;
    int en=k2;
    while(st<=en)
    {
        int l=(st+en)/2;
        if(s2[l]==a1)
            {
                sum++;
                for(int i=l+1;i<=k2;++i)
                    if(s2[i]==a1)
                        sum++;
                    else break;
                for(int i=l-1;i>0;--i)
                    if(s2[i]==a1)
                        sum++;
                    else break;
                return;
            }
        else if(a1<s2[l])
        {
            en=l-1;
        }
        else
        {
            st=l+1;
        }
 
    }
}
int main()
{
    while(cin>>n)
    {
        int k1=1;
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=4; ++j)
                cin>>a[i][j];
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                s1[k1++]=a[i][1]+a[j][2];
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                s2[k2++]=a[i][3]+a[j][4];
        sum=0;
        sort(s2+1,s2+k2);
        k2--;
        for(int i=1; i<k1; ++i)
        {
            judge(-s1[i]);
        }
        printf("%d\n",sum);
    }
}

Given N numbers, X1, X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i  j  N). We can get C(N,2) differences through this work, and now your task is to find the median of the differences as quickly as you can!

Note in this problem, the median is defined as the (m/2)-th  smallest number if m,the amount of the differences, is even. For example, you have to find the third smallest one in the case of = 6.

Input

The input consists of several test cases.
In each test case, N will be given in the first line. Then N numbers are given, representing X1, X2, ... , XN, ( Xi ≤ 1,000,000,000  3 ≤ N ≤ 1,00,000 )

Output

For each test case, output the median in a separate line.

Sample Input

4
1 3 2 4
3
1 10 2

Sample Output

1
8

这个题目一开始做的时候觉得思路并不是很清晰,后来一直在纸上随便写写画画然后灵机一动,知道了思路就是判断小于等于mid的数是否大于所有绝对值个数的一半这一步

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MT(a,b) memset(a,0,sizeof(a))
#define ll long long
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int n,m;
 
 
bool check(int x)
{
    int sum=0;
    for(int i=0;i<n-1;i++)
    {
        int p=upper_bound(a,a+n,a[i]+x)-a;
        sum+=p-i-1;
    }
    return sum>=(m+1)/2;
}
 
 
int main()
{
    while(cin>>n)
    {
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        sort(a,a+n);
        m=n*(n-1)/2;
        int l=0,r=a[n-1]-a[0],ans=(l+r)/2;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

 经过这么长时间学习了,就是总有感觉自己确实付出了很多,但却是自己做的还不够就是继续努力吧,干!

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值