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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章