AtCoderのABC    次のABCの問題へ    前のABCの問題へ

ABC032-C 列

■■■問題■■■

長さNの非負整数列 S=s1,s2, ・・・ ,sN と整数Kがあります。
あなたの仕事は、以下の条件を満たすSの連続する部分列のうち、
最も長いものの長さを求めることです。
部分列の長さは1以上の列でないといけません。

●その部分列に含まれる全ての要素の値の積は、K以下である。

もし条件を満たす部分列が一つも存在しないときは、0を出力してください。

■■■入力■■■

N K
s1
s2
・
・
sN

●1行目には、数列の長さを表す整数 N(1 <= N <= 10万) と
  問題文中の整数 K(0 <= K <= 10億) が空白区切りで与えられる。
●2行目からの N行には、数列の各要素の値が与えられる。
  そのうち i(1 <= i <= N) 行目には、si(0 <= si <= 10億) が書かれている。

■■■出力■■■

1行目に、含まれる全ての要素の値の積がK以下となる連続する部分列のうち最長のものの長さを出力せよ。
もし条件を満たす部分列が一つも存在しないときは、0を出力せよ。末尾の改行を忘れないこと。


C#のソース

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static string InputPattern = "InputX";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("7 6");
            WillReturn.Add("4");
            WillReturn.Add("3");
            WillReturn.Add("1");
            WillReturn.Add("1");
            WillReturn.Add("2");
            WillReturn.Add("10");
            WillReturn.Add("2");
            //4
            //部分列 S[2..5]=s2,s3,s4,s5 を選ぶと、
            //積は 3×1×1×2 = 6 となり、K以下になります。
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("6 10");
            WillReturn.Add("10");
            WillReturn.Add("10");
            WillReturn.Add("10");
            WillReturn.Add("10");
            WillReturn.Add("0");
            WillReturn.Add("10");
            //6
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("6 9");
            WillReturn.Add("10");
            WillReturn.Add("10");
            WillReturn.Add("10");
            WillReturn.Add("10");
            WillReturn.Add("10");
            WillReturn.Add("10");
            //0
        }
        else if (InputPattern == "Input4") {
            WillReturn.Add("4 0");
            WillReturn.Add("1");
            WillReturn.Add("2");
            WillReturn.Add("3");
            WillReturn.Add("4");
            //0
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();
        long[] wkArr = InputList[0].Split(' ').Select(X => long.Parse(X)).ToArray();
        long K = wkArr[1];
        long[] SArr = InputList.Skip(1).Select(X => long.Parse(X)).ToArray();
        int UB = SArr.GetUpperBound(0);

        if (SArr.Contains(0)) {
            Console.WriteLine(SArr.Length);
            return;
        }

        long Answer = 0;
        int L = 0;
        long ProdVal = 1;
        for (int R = 0; R <= UB; R++) {
            ProdVal *= SArr[R];

            while (ProdVal > K) {
                if (L < R) {
                    ProdVal /= SArr[L];
                    L++;
                }
                else break;
            }
            if (ProdVal <= K) {
                if (Answer < R - L + 1)
                    Answer = R - L + 1;

                // 下限値枝切り
                int RestMaxCnt = UB - L + 1;
                if (RestMaxCnt <= Answer) break;
            }
        }
        Console.WriteLine(Answer);
    }
}


解説

尺取法で、IF文を使って、LがRを超えないようにしてます。