Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) ..C. Jury Marks
阿新 • • 發佈:2019-01-05
依舊是STL,用到了map,vector,unique。
題意:一個人有一個額最初的成績,告訴你N個評委的分數(順序),每次評委打完分,都是最初的成績加上字首和,告訴你k個所聽到的成績(隨意的順序),問最初的分數可能是多少。
思路:先預處理出字首和,窮舉每個分數對應的可能最初分數(k[i]-字首和),對應記錄該分數的出現次數,如果==k(滿足k個數都出現的情況)就符合條件,cnt++。 對於這道題必須得用map做,因為字首和可能是負數,如果你開個陣列來hash,那麼要加上4e6,那麼這就很危險把。因為可能會到8e6就炸了。 所以用map來儲存每個 數字 對應的key,然後再查一遍 就可以了。
注意,如果有字首和相同的要剔除,否則一個ki對應同一個初始分數就會出現多次累加,最後答案就會比真實答案要大的。
AC程式碼的後面,附上我很詭異的TLE code
/*If I get TLE , it is good.If I get AC,it's NICE !*/
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e7+10;
const ll mod=1e9+7;
using namespace std;
typedef long long ll;
vector <int> temp;
map <int,int > mp;
int sum[3000];
int main(void)
{
int n,k;
cin >> n>> k;
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
int t;
scanf ("%d",&t);
sum[i]=t+sum[i-1];
}
//for(int i=1;i<=n;i++)
// printf("%d\n",sum[i]);
sort(sum+1,sum+1+n);
int len=unique(sum+1,sum+1+n)-(sum+1);
//for(int i=1;i<=len;i++)
// printf("%d\n",sum[i]);
mp.clear();
//int mmax=-INF;
//int mmin=INF;
for(int i=1;i<=k;i++)
{
int t;
scanf("%d",&t);
for(int j=1;j<=len;j++)
{
temp.push_back(t-sum[j]);
}
}
sort(temp.begin(),temp.end()); // 加上sort AC,不加TLE,比下面的TLE程式碼在更早的測試資料就T了,所以我懷疑map的插入效率可能和原來vector的單調性有關係。越單調,速度越快。
int cnt=0;
//int index=mmax;
for(int i=0;i<temp.size();i++)
{
mp[temp[i]]++;
}
for(int i=0;i<temp.size();i++)
{
if( mp[temp[i]] ==k )
mp[temp[i]]=0,cnt++;
}
printf("%d\n",cnt);
}
// 這個TLE的原因我猜可能是因為每次都要max,min
TLE程式碼
/*If I get TLE , it is good.If I get AC,it's NICE !*/
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e7+10;
const ll mod=1e9+7;
using namespace std;
typedef long long ll;
vector <int> temp;
map <int,int > mp;
int sum[3000];
int main(void)
{
int n,k;
cin >> n>> k;
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
sum[i]=t+sum[i-1];
}
//for(int i=1;i<=n;i++)
// printf("%d\n",sum[i]);
sort(sum+1,sum+1+n);
int len=unique(sum+1,sum+1+n)-(sum+1);
//for(int i=1;i<=len;i++)
// printf("%d\n",sum[i]);
mp.clear();
int mmax=-INF;
int mmin=INF;
for(int i=1;i<=k;i++)
{
int t;
scanf("%d",&t);
for(int i=1;i<=len;i++)
{
mp[t-sum[i]]++;
mmax=max(mmax,t-sum[i]);
mmin=min(mmin,t-sum[i]);
}
}
int cnt=0;
int index=mmax;
for(int i=mmin;i<=index;i++)
{
//printf("%d:%d\n",i,mp[i]);
if(mp[i]==k)
cnt++;
}
printf("%d\n",cnt);
}
最後對STL中unique這個封裝函式解釋一下,這個函式返回沒重複的序列的最後地址,其並沒有把重複的數字刪除,而是放到最後地址的後面了。
會寫unique , 也是這題的一大關鍵。
做完這道題的心得:
1.學習了 STL 中 unique的用法,原理
2.對map插入資料的時候,先用vector儲存,然後再sort,可以大大節省時間。
3.STL真的很重要