1. 程式人生 > >Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) ..C. Jury Marks

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) ..C. Jury Marks

依舊是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真的很重要