Problem:
Score : 400 points

Problem Statement

We have N dice arranged in a line from left to right. The i-th die from the left shows p_i numbers from 1 to p_i with equal probability when thrown.

We will choose K adjacent dice, throw each of them independently, and compute the sum of the numbers shown. Find the maximum possible value of the expected value of this sum.

Constraints

1 ≤ K ≤ N ≤ 200000

1 ≤ p_i ≤ 1000

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N K
p_1 ... p_N

Output

Print the maximum possible value of the expected value of the sum of the numbers shown.

Your output will be considered correct when its absolute or relative error from our answer is at most 10^{-6}.

Sample Input 1

5 3
1 2 2 4 5

Sample Output 1

7.000000000000

When we throw the third, fourth, and fifth dice from the left, the expected value of the sum of the numbers shown is 7. This is the maximum value we can achieve.

Sample Input 2

4 1
6 6 6 6

Sample Output 2

3.500000000000

Regardless of which die we choose, the expected value of the number shown is 3.5.

Sample Input 3

10 4
17 13 13 12 15 20 10 13 17 11

Sample Output 3

32.000000000000

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Numerics;
using System.Text.RegularExpressions;
//byte 255 int<2147483647 ≒ 2 * 10^9 long < 9223372036854775807 ≒ 9 * 10^18
//decimal 29桁

class Myon
{
    //chokudaiさんのコードをコピペ
    static Scanner cin = new Scanner();
    public Myon() { }
    public static int Main()
    {
        int n = cin.nextInt();
        int k = cin.nextInt();
        int[] p = cin.nextIntArr(n);
        long[] p2 = new long[n];
        for(int i = 0; i < n; i++)
        {
            //p2[i] = p[i] * (p[i] + 1) / p[i] / 2;
            p2[i] = (p[i] + 1);

        }
        long tempSumKitaichi = 0;
        for (int i = 0; i < k; i++) tempSumKitaichi += p2[i];
        long tempMaxKitaichi = tempSumKitaichi;
        int tempIndex = 0;
        for(int i = 0; i < n - k; i++)
        {
            tempSumKitaichi = tempSumKitaichi - p2[i] + p2[i + k];
            if(tempMaxKitaichi < tempSumKitaichi)
            {
                tempMaxKitaichi = tempSumKitaichi;
                tempIndex = i;
            }
        }
        
        ShowL((double)tempMaxKitaichi/2);

        return 0;
    }



    public void C()
    {
        int n = cin.nextInt();
        List<int> a = new List<int>();
        a.AddRange(cin.nextIntArr(n));

        int nafter = a.Distinct<int>().Count();

        if (n == nafter) ShowL("YES");
        else ShowL("NO");
    }

    #region utilities
    public static void ShowL() { Console.WriteLine(""); }
    public static void ShowL<T>(T s) { Console.WriteLine(s); }
    public static void Show<T>(T s) { Console.Write(s); }
    public static void Yorn(bool isOK,string ifOK = "Yes",string ifNOTOK ="No") { if (isOK) ShowL(ifOK); else ShowL(ifNOTOK); }

    #endregion utilities
}

class Printer : StreamWriter
{
    public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
    public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
    public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { }
}
class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        while (i >= s.Length)
        {
            string st = Console.ReadLine();
            while (st == "") st = Console.ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
        }
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }

    public int[] nextIntArr(long n)
    {
        int[] output = new int[n];
        for (long i = 0; i < n; i++) output[i] = nextInt();
        return output;
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public long[] nextLongArr(long n)
    {
        long[] output = new long[n];
        for (long i = 0; i < n; i++) output[i] = nextLong();
        return output;
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }

}
static class SMath
{
    
    /// <summary>
    /// 素因数分解して、n番目に見つかった素因数をoutput[n-1]に返します。
    /// 12 なら 2,2,3 です。
    /// </summary>
    /// <param name="n"></param>
    /// <returns></returns>
    public static List<long> Factorization(long n)
    {
        if (n <= 0) return null;
        List<long> output = new List<long>();
        int i = 2;
        long max = (long)Math.Sqrt(n); ;
        while (n > 1)
        {
            if (i > max) { output.Add(n); break; }
            while (n % i == 0)
            {
                output.Add(i);
                n /= i;
            }
            i++;
        }
        return output;
    }

    /// <summary>
    /// 素因数分解して、n番目に見つかった素因数をoutput[n-1]に返します。
    /// 84 = (2^2 * 3 * 7) なら 2, 1, 0, 1 　remainder = 1です。(打ち切られない）
    /// 13 = 0,0,...0 remainder = 2019
    /// ただし、試行を打ち切った時に限り残りをremainderに返す。(remainderは素数または1となる)
    /// </summary>
    /// <param name="n"></param>
    /// <param name="remainder"></param>
    /// <returns></returns>
    public static List<long> Factorization(long n, out long remainder)
    {
        //output[i] が i-1番目の素数の数を示す
        //ただし、試行を打ち切った時に限り残りをremainderに返す。(remainderは素数または1となる)
        remainder = 1;
        if (n <= 0) return null;
        List<long> output = new List<long>();
        long tempn = 2;
        long max = (long)Math.Sqrt(n);
        bool[] isNOTPrime = new bool[max+1];
        while (n > 1)
        {

            if (tempn > max) { remainder = n; break; }
            if (!isNOTPrime[tempn])
            {
                output.Add(0);
                while (n % tempn == 0)
                {
                    output[output.Count - 1]++;
                    n /= tempn;
                }
                for (long j = tempn * 2; j < isNOTPrime.Length; j += tempn) isNOTPrime[j] = true;
            }
            tempn++;
        }
        return output;
    }

    /// <summary>
    /// i番目の素数をoutput[i-1]に返します。
    /// ただしnより大きい素数については判定しません。
    /// </summary>
    /// <param name="n"></param>
    /// <returns></returns>
    public static List<long> GetPrimeNumbers(long n)
    {
        if (n <= 0) return null;
        List<long> output = new List<long>();
        long tempn = 2;
        bool[] isNOTPrime = new bool[n + 1];
        while (n > 1)
        {
            if (tempn > n) { break; }
            if (!isNOTPrime[tempn])
            {
                output.Add(tempn);
                for (long j = tempn * 2; j < isNOTPrime.Length; j += tempn) isNOTPrime[j] = true;
            }
            tempn++;
        }
        return output;
    }


    private static long[][] combMemo;
    private static int maxn_combination = -1;
    public static long Combination(int n, int k)
    {
        if (n < 0 || k > n) return 0;
        if (n == k || k == 0) return 1;
        if (k > n/2) return Combination(n, n - k);
        if (maxn_combination < n)
        {
            maxn_combination = n;
            combMemo = new long[n+1][];
        }
        if (combMemo[n] == null) combMemo[n] = new long[n/2 + 1];
        if (combMemo[n][k] != 0) return combMemo[n][k];
        else
        {
            combMemo[n][k] = Combination(n - 1, k) + Combination(n - 1, k - 1);
            return combMemo[n][k];
        }
        
    }
    public static long Gcd(long a, long b)
    {
        if (a <= 0) return -1;
        //if (a > b) return gcd(b, a);
        if (b == 0) return a;
        return Gcd(b, a % b);
    }
    public static long Lcm(long a,long b)
    {
        return a / Gcd(a, b) * b;
    }


    public class pairComparer : IComparer<int[]>
    {
        int index = 0;
        public pairComparer(int n)
        {
            index = n;
        }
        public pairComparer()
        {
            index = 0;
        }
        public int Compare(int[] x, int[] y)
        {
            return y[index] - y[index];
        }
    }

}