openjudge练习汇总

最近练的都是二分【虽然有的题目用别的神奇的东西A了】,以后会更新的吧…
链接1♂
查找最接近的元素

总时间限制: 1000ms 内存限制: 65536kB
描述
在一个非降序列中,查找与给定值最接近的元素。

输入
第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。
第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000,000之间。
第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。
接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000,000之间。
输出
m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。
样例输入
3
2 5 8
2
10
5
样例输出
8
5

这还是暑假做的,现在差不多都忘了
当时都用的while循环水,然而我还naive的用递归…
没啥好解释的吧【虽然很蠢的调了很久…
果然代码能力太弱啊…
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
LL a[100000+50];
LL n;
LL binary_search(LL left,LL right,LL e)
{   
    LL mid=(left+right)>>1;
    if(left>=1&&right<=n)
    {
        if(a[mid]==e)
            return e;
        else if(left==right&&a[mid]!=e)
        {
            if(a[left]-e>=e-a[left-1])
                return a[left-1];
            return a[left];
        }
        else if(a[mid]<e)
            return binary_search(mid+1,right,e);    
        else if(a[mid]>e)
            return binary_search(left,mid,e);
    }
}
int main()
{
    scanf("%lld",&n);
    for(LL i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    LL m,x;
    scanf("%lld",&m);
    while(m--)
    {
        cin>>x;
        if(x<=a[1])
            cout<<a[1]<<endl;
        else cout<<binary_search(1,n,x)<<endl;
    }
    return 0;
}
/*
3
2 5 8
2
10
5
*/

链接2♂

和为给定数

总时间限制: 1000ms 内存限制: 65536kB
描述
给出若干个整数,询问其中是否有一对数的和等于给定的数。

输入
共三行:
第一行是整数n(0 < n <= 100,000),表示有n个整数。
第二行是n个整数。整数的范围是在0到10^8之间。
第三行是一个整数m(0 <= m <= 2^30),表示需要得到的和。
输出
若存在和为m的数对,输出两个整数,小的在前,大的在后,中间用单个空格隔开。若有多个数对满足条件,选择数对中较小的数更小的。若找不到符合要求的数对,输出一行No。
样例输入
4
2 5 1 4
6
样例输出
1 5

这里写图片描述
mdzz…

暑假是用来当set练习做的,最开始WA到不行,后来才发现要用multiset…然后成功水过…

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
multiset<int>S;
multiset<int>::iterator it;
multiset<int>::iterator it2;
int a[100000+50];
bool flag=0;
int main()
{
    int n,m;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
        S.insert(a[i]);
    cin>>m;
    for(it=S.begin();it!=S.end();it++)
    {
        if(*it<=m)
        {
            it2=S.find(m-*it);
            if(it2!=S.end()&&it2!=it)
            {
                cout<<min(*it,*it2)<<" "<<max(*it,*it2)<<endl;
                flag=1;
                break;
            }
        }
    }
    if(!flag)
        puts("No");
    return 0;
} 

后来又用二分做,第一遍zz把num[mid]写成了mid…结果居然水了70…这数据…
后来重打了一遍,感觉二分边界这东西还是很迷的…后来有WA到不行,才发现忘了判重…【好想发表情来表达我的无语怎么办QAQ
在二分之前不要忘记让序列变得有序…
代码如下(后面带一个自己生成的小数据):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100000+10;
int num[MAXN];
int main()
{
    int n,m;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);
    scanf("%d",&m);
    sort(num+1,num+n+1);
    for(int i=1;i<=n;i++)
    {
        int l=0,r=n;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(num[mid]+num[i]<m)
                l=mid+1;
            else if(num[mid]+num[i]>m)
                r=mid-1;
            else
            {
                //puts("haha");
                if(mid!=i)
                {
                    printf("%d %d\n",min(num[i],num[mid]),max(num[i],num[mid]));
                    return 0;
                }
                else
                {
                    puts("No");
                    return 0;
                }
            }
        }
    }
    puts("No");
    return 0;
}

/*
5
3 0 1 2 5 
5



26
96 38 25 79 8 99 71 49 59 26 96 15 87 19 19 29 14 37 41 56 85 14 2 52 46 50 
23

4
2 5 1 4
6
*/

链接3♂

不重复地输出数

总时间限制: 1000ms 内存限制: 65536kB
描述
输入n个数,从小到大将它们输出,重复的数只输出一次。保证不同的数不超过500个。

输入
第一行是一个整数n。1 <= n <= 100000。
之后n行,每行一个整数。整数大小在int范围内。
输出
一行,从小到大不重复地输出这些数,相邻两个数之间用单个空格隔开。
样例输入
5
2 4 4 5 1
样例输出
1 2 4 5

第一眼,set可以水【对,又是set】
真的,STL大发好啊,成功水过…
代码如下:

#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
set<int>S;
set<int>::iterator it;
int main()
{
    int n,m;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&m);
        S.insert(m);
    }
    for(it=S.begin();it!=S.end();it++)
        cout<<*it<<" ";
    cout<<endl;
    return 0;
}

然后有用桶排水了一波…
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool b[62000000+10];
int main()
{
    int k,l,n;
    cin>>n;
    int hah=0;
    for(int i=1;i<=n;i++)
    {
        cin>>k;
        hah=max(hah,k);
        b[k]=1;
    }
    for(int i=0;i<=hah;i++)
        if(b[i])
            cout<<i<<" ";
    return 0; 
}

然而用二分打了一波,却成功TLE了TAT
感觉这个大水题没人用二分打吧…

还是放一下代码吧,希望各路神犇不要嘲笑蒟蒻啊>_<

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100000+10;
int num[MAXN];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);
    sort(num+1,num+1+n);
    int mn=num[1],mx=num[n];
    num[1]=0;
    //cout<<*lower_bound(num+1,num+1+n,1);
    int last=0;
    while(mn!=mx)
    {
        if(last!=mn)
            printf("%d ",mn);
        last=mn;
        int j=lower_bound(num+1,num+1+n,mn)-num;
        mn=num[j];
        num[j]=0;
    }
    printf("%d\n",mx);
    return 0;
}
/*
5
2 4 4 5 1
*/
发布了38 篇原创文章 · 获赞 1 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章