ブルーブリッジカップの選択された質問シリーズ-ログ統計-足のルール(2018州大会)

まず、例を見る前に、一般的に使用されるアルゴリズムである定規法を紹介します。

ルーラーの概念:

2つのポインターと2つのポインターとも呼ばれる定規法は、アルゴリズムの競合で一般的に使用される最適化手法であり、シーケンス間隔の問題を解決するために使用されます。シンプルな操作と簡単なプログラミング。簡単に言うと、二重ループを単一ループに変換できるため、時間計算量がO(n 2)からO(n)に増加します。

栗を取る:

まず、iとjで実行される二重ループを見てください。

for(int i = 0; i < n; i++)           //i从头扫到尾
    for(int j = n-1; j >= 0; j--){
    
       //j从尾扫到头
        ......
    }

ここで、iは0からn-1にループし、jはn-1から0にループします。これら2つのループの時間計算量はO(n 2)です。
ルーラーメソッドはi、jをループで一緒に処理できます。コードは次のとおりです。したがって、複雑さはO(n 2)からO(n)に変更されます。

for (int i = 0, j = n - 1; i < j; i++, j--) {
    
    
    ......
}

while()を書く別の方法があります:

//用while实现:
int i = 0, j = n - 1;
while (i < j) {
    
          //i和j在中间相遇。这样做还能防止i、j越界
        ......       //满足题意的操作
        i++;         //i从头扫到尾
        j--;         //j从尾扫到头
}

上記は単なる逆スキャンであり、別の同じ方向のスキャンに悩まされています。
ブルーブリッジカップのボスが要約を作成しました。以下を見て理解してください。

円形ポインタiとjはスキャンます。定規方式では、これら2つのポインタiとjには2つのスキャン方向があります。iとjを反対方向に
逆スキャンします。iは最初から最後まで、jは最後から最後までです。初めに、真ん中のミートで。逆方向にスキャンされたiおよびjポインターは、左ポインターおよび右ポインターと呼ばれることもあります。
iとjを最初から最後まで同じ方向にスキャンしますが、速度は異なります。たとえば、jはiの前を走ることができます。同じ方向にスキャンされたiポインターとjポインターは、高速ポインターと低速ポインターとも呼ばれます。このとき、iとjの速度が異なるため、iとjの間のシーケンスで可変サイズのスライディングウィンドウが生成されます。ルーラー方式の利点です。柔軟なアプリケーションがあります。
ルーラーを使用する上で最も重要なことは、2つのポインターiとjが全体で1つのサイクルしか持てないことです。たとえば、iは1回サイクルし、対応するjはiサイクルを1回しか追跡できません。このようにして、O(n 2)からO(n)への計算の複雑さの最適化を実現できます。

次は、C++定規メソッドに似たpythonviolenceメソッドを使用した、州の競争における実際の質問です。

トピックの説明

XiaoMingはプログラマーフォーラムを維持しています。現在、彼は合計N行の「いいね」のログを収集しています。各行の形式は次のとおりです。

ts id

時間tsの番号idの投稿が「いいね」を受け取ったことを示します。

Xiao Mingは、かつて「ホットな投稿」だった投稿を数えたいと考えています。投稿が長さDのいずれかの期間にK件以上のいいねを受け取った場合、XiaoMingはその投稿を「ホット投稿」と見なします。

具体的には、[T、T + D)の期間内に投稿がK件以上のいいねを受け取ることを満足する特定の瞬間Tがある場合(左閉と右開の間隔にあることに注意してください)、投稿かつては「ホットな」投稿でした。

ログを考慮して、Xiaomingが「ホット投稿」であったすべての投稿番号をカウントするのを手伝ってください。

説明を入力してください

最初の行には、3つの整数N、D、Kが含まれています。

次のN行には、1行に1つのログが含まれ、2つの整数tsとidが含まれています。

中、1 <= K <= N <= 10 5、0 <= ts <= 10 5、0 <= id <= 105

出力の説明

ホットポストIDを昇順で出力します。IDごとに1行。

サンプル入力

7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3

サンプル出力

1
3

詳細な回答

上記でルーラーメソッドを紹介しましたが、これは理解として使用できます。この質問でPythonを使用するブルートフォースメソッドは、c ++ルーラーメソッドとほぼ同じ複雑さであるため、ここでは最初にpythonブルートフォースメソッドを使用します(コードは簡単に書くことができます、hehe):

from bisect import bisect_left
maxn=int(1e5+50)
n,d,k=map(int,input().split())
m=[[] for _ in range(maxn)]
post=set()
for _ in range(n):
    ts,idd=map(int,input().split())
    post.add(idd)
    m[idd].append(ts)  #读每个帖子的赞的时间
post = sorted(post)    #对帖子id排序
for idd in post:       #检查每个帖子
    m[idd]=sorted(m[idd])  #把某个帖子的ts排序
    for i in range(len(m[idd])):   #暴力统计这个帖子是不是热帖
        td = m[idd][i]+d
        if(bisect_left(m[idd],td)-i >= k):
            print(idd)
            break

おすすめ

転載: blog.csdn.net/m0_51951121/article/details/122648992
おすすめ