HDU5122

HDU5122

1.トピックリンク

トピックリンク

第二に、主題

NervendingはACMerです。
昨日、NEはアルゴリズムを学びました:バブルソート。バブルソートは、隣接するアイテムの各ペアを比較し、順序が間違っている場合はそれらを交換します。このプロセスは、スワップが不要になるまで繰り返されます。
今日、NEは新しいアルゴリズムを考案し、それをStrangeSortingと名付けました。
ストレンジソーティングには多くのラウンドがあります。NEはラウンドごとに番号を選択し、次の番号がそれよりも小さい間、次の番号と交換し続けます。たとえば、シーケンスが「1 4 3 2 5」で、NEが「4」を選択した場合、このラウンドの後に「1 3 2 45」を取得します。ストレンジソートはバブルソートに似ていますが、NEが各ラウンドの開始時に乱数を選択するため、ランダム化されたアルゴリズムです。NEは、特定のシーケンスについて、最良の状況でこのシーケンスをソートするために必要なラウンド数を知りたいと考えています。つまり、シーケンスを昇順で並べ替えるのに必要な最小限のラウンド数に答える必要があります。問題を単純化するために、NEはシーケンスが1、2、...の順列であることを約束します。、N。

翻訳:

NervendingはACMerです。
昨日、NEはアルゴリズムを学びました:バブルソート。バブルソートは、隣接するアイテムの各ペアを比較し、順序が間違っている場合はそれらを交換します。交換が不要になるまで、このプロセスを繰り返します。
本日、NEは新しいアルゴリズムを提案し、「奇妙な並べ替え」と名付けました。
奇妙な仕分けには多くのラウンドがあります。ラウンドごとに、NEは番号を選択し、次の番号がその番号よりも小さい場合、次の番号と交換し続けます。たとえば、シーケンスが「1 4 3 2 5」で、NEが「4」を選択した場合、このラウンドの後に「1 3 2 45」が取得されます。奇妙な並べ替えはバブル並べ替えに似ていますが、ネットワーク要素が各ラウンドの開始時に乱数を選択するため、ランダムなアルゴリズムです。NEは、特定のシーケンスについて、最良の場合にシーケンスをソートするために必要なラウンド数を知る必要があります。つまり、シーケンスを昇順で並べ替えるのに必要な最小ラウンド数に答える必要があります。問題を単純化するために、NEコミットメントシーケンスは1、2、...のシーケンスです。、N。

入力

最初の行には、テストケースの数を示す整数T(T≤200)が1つだけ含まれています。各テストケースのために、最初の行は、整数N(1≤N≤10含まれている6)。
2行目にはN個の整数ai(1≤ai≤N)が含まれており、NEが与えるシーケンスを示しています。
すべてのテストケースにおけるNの合計は3×10超えない6

出力

テストケースごとに、「Case #x:y」という1行を出力します。ここで、xはケース番号(1から始まります)、yはシーケンスの並べ替えに必要な最小ラウンド数です。

サンプル入力

2
5
5 4 3 2 1
5
5 1 2 3 4

サンプル出力

ケース#1:4
ケース#2:1

三、質問は分解されます

  • まず第一に、私たちがしなければならないことは、ソートの最小ラウンドを計算することであることがわかっています。次に、タイトルの大まかに与えられたコンテンツを見てみましょう。

ラウンドごとに、NEは番号を選択し、次の番号がその番号よりも小さい場合、次の番号と交換し続けます。たとえば、シーケンスが「1 4 3 2 5」で、NEが「4」を選択した場合、このラウンドの後に「1 3 2 45」が取得されます。

  • どういう意味ですか?番号を選択すると、この番号は常にこのラウンドの番号よりも小さい番号と交換されるため、このラウンドの番号は、その後ろの番号がそれよりも大きいことを保証します。
  • ここで注意すべきことの1つはその背後にある数それよりも大きく、その背後にあるすべての数字ではありません。
  • いいです!次に、次のトピックを見ていきます。

奇妙な並べ替えはバブル並べ替えに似ていますが、ネットワーク要素が各ラウンドの開始時に乱数を選択するため、ランダムなアルゴリズムです。NEは、特定のシーケンスについて、最良の場合にシーケンスをソートするために必要なラウンド数を知る必要があります。つまり、シーケンスを昇順で並べ替えるのに必要な最小ラウンド数に答える必要があります。

  • ここでのタイトルの意味は明らかです。最小のラウンドで昇順になるように数値を選択する方法を見つける必要があります。
  • データ範囲

T≤200
1≤N≤10 6
データ和<= 3×10 6

4つの問題解決のアイデア

  • それでは、タイトルの「奇妙な並べ替え」の動作ロジックを分析してみましょう。
  1. ランダムに番号を選択します
  2. それよりも大きな数に遭遇するまで、それを「シンク」にします。
  3. シーケンスが昇順になるまで、手順1〜2を繰り返します。
  • では、どうすればこのラウンドを最小化できますか?
    非常に簡単です。各ラウンドで配列内の最大の要素を選択するため、最大のラウンドでもn回しか実行されません。
  • では、この最小ラウンドをどのように計算するのでしょうか?
    まず、配列内のどの数値を「シンク」する必要があるかを判断し、これらの数値の数を見つける必要があります。これは、必要な最小ラウンド数です。では、これらの数をどのように見つける必要がありますか?
  • 数値が配列に「シンク」する必要がある理由は何ですか?その下に「軽い」数字があるので、その下に「軽い」数字がある数字を確認するだけで済みます。
    具体的なアイデア
  • 配列の最後の桁から配列の先頭までトラバースし、配列の現在の位置で最小の数値を記録し、現在の数値が最小の数値より大きい場合は、ラウンド+1にします。
  • 次に例を示します。5443
    1 2
    0に初期化されるラウンドサムを定義します。配列の現在の最小数minを、配列の最後の桁と等しくなるように定義してから、配列の最後から2番目の桁。
  • i = 1、1にスキャン、min = 2 <1、minを更新、この時点でmin = 1、sum = 0
  • i = 2、スキャンして3、min = 1> 3、数値をシンクする必要がある、sum ++、minは変更されない、配列の並べ替えは5 4 1 2 3
  • i = 3、4までスキャン、min = 1> 4、数値シンク、sum ++
  • i = 4、5までスキャン、最小> 5、数値シンク、合計++
  • 出力結果sum = 3

五、コード

#include "iostream"
using namespace std;
int main()
{
    
    
    int n;
    scanf("%d",&n);//输入样例数
    for(int i=1;i<=n;i++)
    {
    
    
        int t;//数组大小
        scanf("%d",&t);
        int a[t+5];
        for(int g=0;g<t;g++)
        {
    
    
            scanf("%d",&a[g]);//用scanf可以防止数据过多超时
        }
        int sum=0;//定义轮次
        int mnum=a[t-1];//定义当前最小数字,使其等于数组末尾数字
        for(int g=t-2;g>=0;g--)
        {
    
    
            if(a[g]>mnum)//如果当前数字大于最小数字,说明数字需要下沉
            {
    
    
                sum++;
            } else//如果不需要下沉,更新最小数
            {
    
    
                mnum=a[g];
            }
        }
        printf("Case #%d: %d\n",i,sum);
    }
}

  • 注意すべき点は、同時にプラグインするためにcinを使用しないことです。

ios :: sync_with_stdio(false);

  • タイムアウトする場合は、scanfを使用してデータを入力することをお勧めします。

おすすめ

転載: blog.csdn.net/Verber/article/details/112907593