1. 程式人生 > >2018年藍橋杯B組c/c++ 第八題詳解

2018年藍橋杯B組c/c++ 第八題詳解

標題:日誌統計

小明維護著一個程式設計師論壇。現在他收集了一份"點贊"日誌,日誌共有N行。其中每一行的格式是:

ts id

表示在ts時刻編號id的帖子收到一個"贊"。

現在小明想統計有哪些帖子曾經是"熱帖"。如果一個帖子曾在任意一個長度為D的時間段內收到不少於K個贊,小明就認為這個帖子曾是"熱帖"。

具體來說,如果存在某個時刻T滿足該帖在[T, T+D)這段時間內(注意是左閉右開區間)收到不少於K個贊,該帖就曾是"熱帖"。

給定日誌,請你幫助小明統計出所有曾是"熱帖"的帖子編號。

【輸入格式】
第一行包含三個整數N、D和K。
以下N行每行一條日誌,包含兩個整數ts和id。

對於50%的資料,1 <= K <= N <= 1000
對於100%的資料,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000

【輸出格式】
按從小到大的順序輸出熱帖id。每個id一行。

【輸入樣例】
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3

【輸出樣例】
1
3

資源約定:
峰值記憶體消耗(含虛擬機器) < 256M
CPU消耗 < 1000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入…” 的多餘內容。

注意:
main函式需要返回0;
只使用ANSI C/ANSI C++ 標準;
不要呼叫依賴於編譯環境或作業系統的特殊函式。
所有依賴的函式必須明確地在原始檔中 #include
不能通過工程設定而省略常用標頭檔案。

提交程式時,注意選擇所期望的語言型別和編譯器型別。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#define MAX 100005
using namespace std;
vector<int> m[MAX];
int n, d, k;

/*
判斷id為i的帖子是否為熱帖,是則返回 true 否則返回 false;
    判斷是否為熱帖的方法,對每個帖子對應的所有時間進行排序,
    用尺取法找到在 d 時間範圍內的達到 k 個讚的帖子
*/
bool judge(int x){
    int len = m[x].size();
    if(len < k){
        return false;
    }
    sort(m[x].begin(), m[x].end());
    int l = 0;      //左
    int r = 0;      //右
    int sum = 0;    //尺子長度
    while(l <= r && r < len){
        //r++;  注意:r++不能寫到這裡需要先進行判斷在移動右邊,
        //如果非要寫到這裡的話,sum = 1在初始化的時候應該需要初始化為1
        sum++;
        if(sum >= k){
            if(m[x][r] - m[x][l] < d){
                return true;
            }else{
                l++;
                sum--;
            }
        }
        r++;
    }
    return false;
}
int main(){
    cin >> n >> d >> k;
    int ts, id;
    for(int i = 0; i < n; i++){
        cin >> ts >> id;
        m[id].push_back(ts);
    }
    //int index = 0;
    for(int i = 0; i < MAX; i++){
        if(judge(i)){
            cout << i <<  endl;
            //num[index++] = i;
        }
    }
    return 0;
}