1. 程式人生 > >2017網絡新生賽2305the count of num心得

2017網絡新生賽2305the count of num心得

問題分析 等於 .... using main 數據文件 分析 心得 tchar

題目描述:

有n個整數(1<=n<=200000),分別為a1, a2, a3, ..., an。對於第i個整數ai,它的範圍為0~10^9, 有k個整數(1<=k<=200000),分別為M1, M2, M3, ..., Mk。對於第i個整數Mi,它的範圍為0~10^9。你的任務是對M1, M2, M3, ..., Mk這k個整數分別查找它們在a1, a2, a3, ...., an這個序列裏出現的次數。

輸入描述:

有多組數據。每組數據3行。結束標誌為EOF。

第一行輸入為兩個整數n, k(1<=n, k<=200000)。N為整數的個數,k為數據的組數。

第二行輸入為n個整數,分別為a1, a2, a3, ..., an。對於第i個整數ai,它的範圍為0~10^9。整數之間間隔為一個空格。

第三行為k個整數。分別為M1, M2, M3, ..., Mk。對於第i個整數Mi,它的範圍為0~10^9。整數之間間隔為一個空格。

每一個數據文件有多組數據,但保證每一個數據文件裏的每組數據的n的和不超過200000,每一個數據文件裏的每組數據的k的和不超過200000。

比如下面的樣例輸入,出現了兩個n和k,每個n和k的範圍都在1~200000以內且兩個n的和不超過200000,兩個k的和也不超過200000。

輸出描述:

對於每組數據輸出一行。對於每個Mi,輸出在a1, a2, a3, ..., an這個序列裏出現的次數。數與數之間需要間隔一個空格。註意這行最後不能出現空格。

輸入樣例:

5 5
1 2 3 4 5
3 5 2 4 1
10 10
656 649 1646 1322 123 649 3201 9850 1245 3200
666 110 1000 649 9850 121 123 9850 1244 1646

輸出樣例:

1 1 1 1 1
0 0 0 2 1 0 1 0 1

問題分析:

這道題目,我第一個想到的就是二分查找,因為數據量有點大,我們只需要先將數組排序,然後二分查找第一個出現該數字的位置,再從該位置向前向後遍歷就好。但是,這樣子,復雜度依然很大,於是,,我想到一種新的方法,其實,也很簡單,就是在找到第一個出現該數字的位置時,繼續二分查找該數字出現的上界和下界,相減加一就是該數字在數組中出現的次數。很好,其實本題並不難,主要是為了優化時間,要二分查找上界和下界。下面上代碼:

#include <iostream>
#include <cstdio>
#include <algorithm>
const int Maxn = 200000;
using namespace std;


int Find(int a[],int low,int high,int t)
{
int m;
while (low <= high)
{
m = low + (high - low) / 2;
if(a[m] < t)
{
low = m + 1;
}
else if(a[m] > t)
{
high = m - 1;
}
else
{
return m;
}
}
if(a[low] == t)
{
return low;
}
return -1;
}
int main(void)
{
int i,n,m,t,p,sum,j,a[Maxn],m1,m2,m3;//m1,m2用來保存上界和下界
while (~scanf ("%d%d",&n,&t))
{
for (i = 0; i < n; i++)
{
scanf ("%d",&a[i]);
}
sort(a,a + n);
for (i = 1; i <= t; i++)
{
sum = 0;
scanf ("%d",&p);
m = Find(a,0,n - 1,p);
//printf ("%d %d\n",p,m);
if(m == -1)
{
sum = 0;
}
else
{
m3 = m;
if(m != n - 1)
{

//查找數字出現的上界,用m1保存
while (a[m + 1] == a[m])
{
m = Find(a,m + 1,n - 1,p);
}
}
m1 = m;
if(m3 != 0)
{

//查找數字出現的下界,用m2保存
while (a[m3 - 1] == a[m3])
{
m3 = Find(a,0,m3 - 1,p);
}
}
m2 = m3;

//上界減去下界+1等於該數字在數組上出現的次數
sum += (m1 - m2 + 1);
}
printf ("%d",sum);
if(i < t)
{
putchar(‘ ‘);
}
}
putchar(‘\n‘);
}
return 0;
}

2017網絡新生賽2305the count of num心得