字節跳動2018校招後端方向 [編程題]用戶喜好

題目描述:

時間限制:C/C++ 3秒,其他語言6秒

空間限制:C/C++ 256M,其他語言512M

爲了不斷優化推薦效果,今日頭條每天要存儲和處理海量數據。假設有這樣一種場景:我們對用戶按照它們的註冊時間先後來標號,對於一類文章,每個用戶都有不同的喜好值,我們會想知道某一段時間內註冊的用戶(標號相連的一批用戶)中,有多少用戶對這類文章喜好值爲k。因爲一些特殊的原因,不會出現一個查詢的用戶區間完全覆蓋另一個查詢的用戶區間(不存在L1<=L2<=R2<=R1)。

思路:

我的思路:

因爲詢問區間保證了不會出現覆蓋,那麼如果將詢問區間對左端點排序的話,就會出現下圖這樣

也就是說,如果對左端點排序,右端點一定是不斷變大的。因爲l1<=l2,所以r2>r1一定成立,否則就會與條件衝突。

所以我們維護雙指針,用sum[maxn]標記離散化後的數i在已經掃過的區域內出現的次數的和。

右指針右移,sum[a[i]]++,左指針右移,sum[a[i]]--,這樣就像是一個前綴和的性質,掃一遍複雜度O(n),還有離散化操作,應該是O(nlogn)的複雜度。

但是我只過了70%,沒有檢查出錯,可能是數據隨機並沒有滿足題目中的條件,也希望各位大佬幫我查查錯。

#include <bits/stdc++.h>
using namespace std;

const int maxn=3e5+10;
vector<int>v;
int getid(int cur){
    return lower_bound(v.begin(),v.end(),cur)-v.begin()+1;
}

struct Node{
    int l,r;
    int k;
    int id;
}node[maxn];
int a[maxn];
int sum[maxn];
int ans[maxn];
int cmp(const Node a,const Node b){
    return a.l<b.l||(a.l==b.l&&a.r<b.r);
}
signed main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        v.push_back(a[i]);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].k);
        node[i].id=i;
    }
    sort(node+1,node+q+1,cmp);
    int l=1,r=1;
    int cur=1;
    while(cur<=q){
        while(r<=node[cur].r){
            sum[getid(a[r])]++;
            r++;
        }
        while(l<node[cur].l){
            sum[getid(a[l])]--;
            l++;
        }
        int now=sum[getid(node[cur].k)];
        ans[node[cur].id]=now;
        cur++;
    }
    for(int i=1;i<=q;i++){
        printf("%d\n",ans[i]);
    }
    return 0;

}

大佬的思路:

簡單明瞭,維護一個值k的出現序列vector,如果有詢問l,r,k,直接在vector中二分到l-1和r這個區間,看這個區間的長度有多長,就說明這個區間內有多少個k,不得不說這是我見過最簡單明瞭的思路了。

#include <bits/stdc++.h>
using namespace std;
map<int, vector<int> >ma;
int n, q, t;
int l, r, k;
int solve(int l, int r, int k) {
    if (ma[k].size() == 0) return 0;
    auto it1 = lower_bound(ma[k].begin(), ma[k].end(), l);
    auto it2 = upper_bound(ma[k].begin(), ma[k].end(), r);
    return it2 - it1;
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> t;
        ma[t].push_back(i);
    }
 
    cin >> q;
    for (int i = 0; i < q; ++i) {
        cin >> l >> r >> k;
        cout << solve(l, r, k) << endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章