import Foundation

let main: () = {
    let (N, M) = *listOfInt()
    var U = UnionFind(N)
    repeate(M) {
        let (A, B) = *listOfInt(-1)
        U.unite(A, B)
    }
    var ans = 0
    for n in 0 ..< N {
        let size = U.size(n)
        if ans < size { ans = size }
    }
    print(ans)
}()

//----------------------------------

let dx = [1, 0, -1, 0] //[1, 0, -1, 0, -1,  1, -1, 1]
let dy = [0, 1, 0, -1] //[0, 1, 0, -1, -1, -1,  1, 1]

@inlinable func gcd(_ a: Int, _ b: Int) -> Int { (b > 0) ? gcd(b, a % b) : a }
@inlinable func lcm(_ a: Int, _ b: Int) -> Int { a / gcd(a, b) * b }

//----------------------------------

infix operator  =~ : ComparisonPrecedence
infix operator !=~ : ComparisonPrecedence
func =~ <T: FixedWidthInteger>(left: T, right: Range<T>) -> Bool { right ~= left }
func !=~ <T: FixedWidthInteger>(left: T, right: Range<T>) -> Bool { !(right ~= left) }
func =~ <T: FixedWidthInteger>(left: T, right: ClosedRange<T>) -> Bool { right ~= left }
func !=~ <T: FixedWidthInteger>(left: T, right: ClosedRange<T>) -> Bool { !(right ~= left) }

func =~ <T: Collection > (left: T.Element, right: T) -> Bool where T.Element : Equatable { right.contains(left) }
func !=~ <T: Collection > (left: T.Element, right: T) -> Bool where T.Element : Equatable { !right.contains(left) }

infix operator /^ : MultiplicationPrecedence
infix operator /^= : AssignmentPrecedence
func /^ <T: FixedWidthInteger>(left: T, right: T) -> T { (left + (right - 1)) / right }
func /^= <T: FixedWidthInteger>(left: inout T, right: T) { left = (left + (right - 1)) / right }

@inlinable func chmax<T: Comparable>(_ m: inout T, _ q: T) { if (m < q) { m = q } }
@inlinable func chmin<T: Comparable>(_ m: inout T, _ q: T) { if (m > q) { m = q } }
@inlinable func chRmax<T: Comparable>(_ m: inout T, _ q: T) -> Bool { if (m < q) { m = q; return true } else { return false } }
@inlinable func chRmin<T: Comparable>(_ m: inout T, _ q: T) -> Bool { if (m > q) { m = q; return true } else { return false } }

prefix operator *
prefix func * <T> (a: [T]) -> (T, T) { (a[0], a[1]) }
prefix func * <T> (a: [T]) -> (T, T, T) { (a[0], a[1], a[2]) }
prefix func * <T> (a: [T]) -> (T, T, T, T) { (a[0], a[1], a[2], a[3]) }
prefix func * <T> (a: [T]) -> (T, T, T, T, T) { (a[0], a[1], a[2], a[3], a[4]) }
prefix func * <T> (a: [T]) -> (T, T, T, T, T, T) { (a[0], a[1], a[2], a[3], a[4], a[5]) }

func printErr(_ str: String, terminator: String = "\n") {
    let s = str + terminator
    FileHandle.standardError.write(s.data(using: .utf8)!)
    FileHandle.standardError.synchronizeFile()
}

@inlinable func next() -> String { readLine()! }
@inlinable func nextInt() -> Int { Int(next())! }
@inlinable func nextDouble() -> Double { Double(next())! }
@inlinable func listOfString() -> [String] { next().split(separator: " ").map(String.init) }
@inlinable func listOfInt() -> [Int] { listOfString().map { Int($0)! } }
@inlinable func listOfInt(_ offset: Int = 0) -> [Int] { listOfString().map { Int($0)! + offset } }
@inlinable func listOfInt(_ offsets: Int ...) -> [Int] { listOfString().enumerated().map { Int($0.element)! + offsets[$0.offset % offsets.count] } }
@inlinable func listOfDouble(_ offset: Double = 0.0) -> [Double] { listOfString().map { Double($0)! + offset } }
@inlinable func listOfDouble(_ offsets: Double ...) -> [Double] { listOfString().enumerated().map { Double($0.element)! + offsets[$0.offset % offsets.count] } }

extension Int {
    init(s: String) { self.init(s)! }
    var isEven: Bool { self.isMultiple(of: 2) }
    var isOdd: Bool { !self.isEven }
    var isTrue: Bool { self != 0 }
    var isFalse: Bool { !self.isTrue }
    var toString: String { String(self) }
    var toChar: Character { Character(UnicodeScalar(UInt8(self))) }
}
func + (left: Int, right: Bool) -> Int { left + (right ? 1 : 0) }
extension Character {
    var asciiCode: Int { Int(self.asciiValue!) }
    var string: String { String(self) }
}
extension String {
    @inlinable subscript (position: Int) -> Character { self[self.index(self.startIndex, offsetBy: position)] }
    @inlinable func repeate(_ times: Int) -> String { String(repeating: self, count: times) }
    //  @inlinable subscript (n: Int) -> String { String(self[self.index(self.startIndex, offsetBy: n)]) }
    //  @inlinable subscript (n: Int) -> Int { Int(self[self.index(self.startIndex, offsetBy: n)].asciiValue!) }
    var toInt: Int { Int(self)! }
}
extension String { // VB like
    @inlinable func _index(_ position: Int) -> String.Index! {
        if !(0 ..< self.count ~= position) { return nil }
        return self.index(self.startIndex, offsetBy: position)
    }
    @inlinable func mid(from index: Int, length: Int) -> String! {
        if let startPosition = self._index(index) {
            if let endPosition = self._index(index + length - 1) {
                return String(self[startPosition...endPosition])
            } else {
                let endPosition = self.index(before: self.endIndex)
                return String(self[startPosition...endPosition])
            }
        }
        return ""
    }
    @inlinable func left(_ length: Int) -> String { String(self.prefix(length)) }
    @inlinable func right(_ length: Int) -> String { String(self.suffix(length)) }
}

extension Dictionary {
    @inlinable mutating func getOrSet(_ key: Key, _ defaultValue: () -> Value) -> Value {
        if let stored = self[key] { return stored }
        else {
            let newValue = defaultValue()
            self[key] = newValue
            return newValue
        }
    }
    @inlinable mutating func getOrElse(_ key: Key, _ defaultValue: () -> Value) -> Value {
        if let stored = self[key] { return stored } else { return defaultValue() }
    }
    @inlinable func containsKey(_ key: Key) -> Bool { self.keys.contains(key) }
}

extension Set {
    static func += (left: inout Set<Element>, right: Element) { left.insert(right) }
    static func -= (left: inout Set<Element>, right: Element) { left.remove(right) }
}

extension Array {
    static func += (left: inout Array<Element>, right: Element) { left.append(right) }
    init(_ size: Int, _ initValue: ((Int) -> Element)) {
        self = [Element]()
        for index in 0 ..< size {
            let value = initValue(index)
            self.append(value)
        }
    }
    init(_ size: Int, _ initValue: (() -> Element)) {
        self = [Element]()
        for _ in 0 ..< size {
            let value = initValue()
            self.append(value)
        }
    }
}
typealias IntArray = Array<Int>
typealias DoubleArray = Array<Double>
typealias BoolArray = Array<Bool>
typealias StringArray = Array<String>

extension Array where Element == Int {
    init(_ size: Int) {
        self = [Element](repeating: 0, count: size)
    }
}
extension Array where Element == Double {
    init(_ size: Int) {
        self = [Element](repeating: 0.0, count: size)
    }
}
extension Array where Element == Bool {
    init(_ size: Int) {
        self = [Element](repeating: false, count: size)
    }
}
extension Array where Element == String {
    init(_ size: Int) {
        self = [Element](repeating: "", count: size)
    }
}

extension Array {
    @inlinable func count(_ predicate: ((Element) -> Bool)) -> Int {
        var cnt = 0; for e in self { if (predicate(e)) { cnt += 1 } }
        return cnt
    }
    @inlinable func groupBy<K>(_ keySelector: (Element) -> K) -> [K : [Element]] {
        var destination = [K : [Element]]()
        for element in self {
            let key = keySelector(element)
            var list = destination.getOrSet(key) { [Element]() }
            list.append(element)
            destination[key] = list
        }
        return destination
    }
    @inlinable func groupByIndexed<K>(_ keySelector: (Element) -> K) -> [K : [Int]] {
        var destination = [K : [Int]]()
        for element in self.enumerated() {
            let key = keySelector(element.element)
            var list = destination.getOrSet(key) { [Int]() }
            list.append(element.offset)
            destination[key] = list
        }
        return destination
    }
}

extension Array {
    func binarySearch(_ element: Element, by compare: (Element, Element) -> Int, fromIndex: Int = 0, toIndex: Int = -1) -> Int {
        var low = fromIndex
        var high = (toIndex == -1) ? self.count - 1 : toIndex - 1
        while (low <= high) {
            let mid = (low + high) >> 1 // safe from overflows
            let midVal = self[mid]
            let cmp = compare(midVal, element)
            if (cmp < 0) { low = mid + 1 }          //-1
            else if (0 < cmp) { high = mid - 1 }    // 1
            else { return mid } // key found        // 0
        }
        return -(low + 1)  // key not found
    }
}
extension Array where Element : Comparable {
    func binarySearch(_ element: Element, fromIndex: Int = 0, toIndex: Int = -1) -> Int {
        var low = fromIndex
        var high = (toIndex == -1) ? self.count - 1 : toIndex - 1
        while (low <= high) {
            let mid = (low + high) >> 1 // safe from overflows
            let midVal = self[mid]
            if (midVal < element) { low = mid + 1 }
            else if (midVal > element) { high = mid - 1 }
            else { return mid } // key found
        }
        return -(low + 1)  // key not found
    }
}

extension Array where Element == Int {
    @inlinable func distinct() -> [Element] {
        var set = Set<Element>(), ary = [Element]()
        for n in self.indices { if !set.contains(self[n]) { ary.append(self[n]); set.insert(self[n]) } }
        return ary
    }
    @inlinable func any(_ predicate: (Element) -> Bool) -> Bool {
        var any = false; for element in self { if predicate(element) { any = true } }
        return any
    }
    @inlinable func all(_ predicate: (Element) -> Bool) -> Bool {
        self.allSatisfy(predicate)
    }
    @inlinable func sum() -> Element { self.reduce(0, +) }
    @inlinable func sum(by predicate: (Element) -> Element) -> Element {
        var sum = 0; for e in self { sum += predicate(e) }
        return sum
    }
    @inlinable func joinToString(_ sepatator: String = " ") -> String { self.map { String($0) }.joined(separator: sepatator) }
}

extension Array where Element == Double {
    @inlinable func sum() -> Element { self.reduce(0.0, +) }
    @inlinable func sum(by predicate: (Element) -> Element) -> Element {
        var sum = 0.0; for e in self { sum += predicate(e) }
        return sum
    }
    @inlinable func joinToString(_ sepatator: String = " ") -> String { self.map { String($0) }.joined(separator: sepatator) }
}
extension Array where Element == String {
    @inlinable func toIntDouble() -> (Int, Double) { (Int(self[0])!, Double(self[1])!) }
    @inlinable func toIntString() -> (Int, String) { (Int(self[0])!, self[1]) }
    @inlinable func toIntIntString() -> (Int, Int, String) { (Int(self[0])!, Int(self[1])!, self[2]) }
}

@inlinable func block( _ action: () -> Void) {
    action()
}
@inlinable func repeate(_ times1: Int, _ action: () -> Void) {
    for _ in 0 ..< times1 { action() }
}
@inlinable func repeate(_ times1: Int, _ action: (Int) -> Void) {
    for index1 in 0 ..< times1 {
        action(index1)
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ action: (Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            action(index1, index2)
        }
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ times3: Int, _ action: (Int, Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            for index3 in 0 ..< times3 {
                action(index1, index2, index3)
            }
        }
    }
}
@inlinable func repeate(_ times1: Int, _ times2: Int, _ times3: Int, _ times4: Int, _ action: (Int, Int, Int, Int) -> Void) {
    for index1 in 0 ..< times1 {
        for index2 in 0 ..< times2 {
            for index3 in 0 ..< times3 {
                for index4 in 0 ..< times4 {
                    action(index1, index2, index3, index4)
                }
            }
        }
    }
}

func measureTimeSeconds(block: (() -> Void)) -> Double {
    let startTime = Date()
    block()
    let duration = -startTime.timeIntervalSinceNow
    return duration
}

struct UnionFind {
    var rank: [Int]
    var par:  [Int]
    var size: [Int]
    init(_ size: Int) {
        self.rank = IntArray(size) { 0 }
        self.par  = IntArray(size) { $0 }
        self.size = IntArray(size) { 1 }
    }
    @discardableResult
    mutating func unite(_ x: Int, _ y: Int) -> Bool {
        var rx = self.root(x)
        var ry = self.root(y)
        if (rx == ry) { return false }
        if (self.rank[rx] < self.rank[ry]) {
            let w = rx
            rx = ry
            ry = w
        } else if (self.rank[rx] == self.rank[ry]) {
            self.rank[rx] += 1
        }
        self.par[ry] = rx
        self.size[rx] += self.size[ry]
        return true
    }
    mutating func find(_ x: Int) -> Int {
        if (self.par[x] == x) { return x }
        else {
            self.par[x] = self.find(self.par[x])
            return self.par[x]
        }
    }
    mutating func isSame(_ x: Int, _ y: Int) -> Bool { self.root(x) == self.root(y) }
    mutating func size(_ x: Int) -> Int { self.size[self.find(x)] }
    mutating func root(_ x: Int) -> Int { self.find(x) }
}


func readTwoInts(separator: String.Element = " ") -> (a: Int, b: Int) {
    let ints = readLine()!.split(separator: separator).map { Int($0)! }
    return (a: ints[0], b: ints[1])
}

func mainD() {
    let (N, M) = readTwoInts()
    let pairs = (0..<M).map { _ in readTwoInts() }

    var groups: [Set<Int>] = (1...N).map { Set(arrayLiteral: $0) }
    pairs.forEach { pair in
        groups[pair.a - 1].insert(pair.b)
        groups[pair.b - 1].insert(pair.a)
    }

    pairs.forEach { pair in
        for id in groups[pair.a - 1] {
            groups[pair.b - 1].insert(id)
        }

        for id in groups[pair.b - 1] {
            groups[pair.a - 1].insert(id)
        }
    }

    // それぞれの直接の友達をセットアップ(片側だけ)
//    var persons: [Person] = (1...N).map { Person(id: $0) }
//    pairs.forEach { pair in
//        persons[pair.a - 1].friends.insert(pair.b)
//        persons[pair.b - 1].friends.insert(pair.a)
//    }

//    var groups: [Set<Int>] = []
//    for person in persons {
//        var needNewGroup = true
//
//        for i in (0..<groups.count) {
//            if !groups[i].intersection(person.friends).isEmpty {
//                needNewGroup = false
//
//                groups[i].insert(person.id)
//                for id in person.friends {
//                    groups[i].insert(id)
//                }
//                break
//            }
//        }
//
//        if needNewGroup {
//            var newGroup = Set(person.friends)
//            newGroup.insert(person.id)
//            groups.append(newGroup)
//        }
//    }

    // 最大人数の判定
    print(groups.map { $0.count }.max()!)
}
mainD()


func readTwoInts(separator: String.Element = " ") -> (a: Int, b: Int) {
    let ints = readLine()!.split(separator: separator).map { Int($0)! }
    return (a: ints[0], b: ints[1])
}

func mainD() {
    let (N, M) = readTwoInts()
    let pairs = (0..<M).map { _ in readTwoInts() }

    var groups: [Set<Int>] = (1...N).map { Set(arrayLiteral: $0) }
    pairs.forEach { pair in
        groups[pair.a - 1].insert(pair.b)
        groups[pair.b - 1].insert(pair.a)
    }

    // それぞれの直接の友達をセットアップ(片側だけ)
//    var persons: [Person] = (1...N).map { Person(id: $0) }
//    pairs.forEach { pair in
//        persons[pair.a - 1].friends.insert(pair.b)
//        persons[pair.b - 1].friends.insert(pair.a)
//    }

//    var groups: [Set<Int>] = []
//    for person in persons {
//        var needNewGroup = true
//
//        for i in (0..<groups.count) {
//            if !groups[i].intersection(person.friends).isEmpty {
//                needNewGroup = false
//
//                groups[i].insert(person.id)
//                for id in person.friends {
//                    groups[i].insert(id)
//                }
//                break
//            }
//        }
//
//        if needNewGroup {
//            var newGroup = Set(person.friends)
//            newGroup.insert(person.id)
//            groups.append(newGroup)
//        }
//    }

    // 最大人数の判定
    print(groups.map { $0.count }.max()!)
}
mainD()


func readTwoInts(separator: String.Element = " ") -> (a: Int, b: Int) {
    let ints = readLine()!.split(separator: separator).map { Int($0)! }
    return (a: ints[0], b: ints[1])
}

func mainD() {
    let (N, M) = readTwoInts()
    let pairs = (0..<M).map { _ in readTwoInts() }

    var groups: [Set<Int>] = (1...N).map { Set(arrayLiteral: $0) }
    pairs.forEach { pair in
        groups[pair.a - 1].insert(pair.b)
        groups[pair.b - 1].insert(pair.a)
    }

    pairs.forEach { pair in
        for id in groups[pair.a - 1] {
            groups[pair.b - 1].insert(id)
        }
    }

    // それぞれの直接の友達をセットアップ(片側だけ)
//    var persons: [Person] = (1...N).map { Person(id: $0) }
//    pairs.forEach { pair in
//        persons[pair.a - 1].friends.insert(pair.b)
//        persons[pair.b - 1].friends.insert(pair.a)
//    }

//    var groups: [Set<Int>] = []
//    for person in persons {
//        var needNewGroup = true
//
//        for i in (0..<groups.count) {
//            if !groups[i].intersection(person.friends).isEmpty {
//                needNewGroup = false
//
//                groups[i].insert(person.id)
//                for id in person.friends {
//                    groups[i].insert(id)
//                }
//                break
//            }
//        }
//
//        if needNewGroup {
//            var newGroup = Set(person.friends)
//            newGroup.insert(person.id)
//            groups.append(newGroup)
//        }
//    }

    // 最大人数の判定
    print(groups.map { $0.count }.max()!)
}
mainD()


// @ts-ignore
import * as fs from 'fs';

// main
function main(input: string[]) {
    // param
    var n: number;
    var m: number;
    var am: number[] = [];
    var bm: number[] = [];
    // init
    [n, m] = input.shift().split(" ").map(x => Number(x));
    for (var mx = 0; mx < m; mx ++) {
        [am[mx], bm[mx]] = input[mx].split(" ").map(x => Number(x) - 1);
    }
    // process
    UF_initRoot(n);
    for (var mx = 0; mx < m; mx ++) {
        UF_mergeRoot(am[mx], bm[mx]);
    }
    // answer
    console.log(Math_max(g_uf_count));
}

// math library
function Math_max(arr: number[]): number { return arr.reduce((x, y) => Math.max(x, y)); }
function Math_min(arr: number[]): number { return arr.reduce((x, y) => Math.min(x, y)); }
function Math_gcd(): number {
    var ans = arguments[0];
    var f = (a: number, b: number): number => b ? f(b, a % b) : a
    for (var i = 1; i < arguments.length; i++) {
        ans = f(ans, arguments[i]);
    }
    return ans
};
function Math_gcdArray(val: number[]): number {
    var ans = val[0];
    var f = (a: number, b: number): number => b ? f(b, a % b) : a
    for (var i = 1; i < val.length; i++) {
        ans = f(ans, val[i]);
    }
    return ans
};
function Math_lcm(): number {
    var a = arguments
    var g = (n: number, m: number): number => m ? g(m, n % m) : n
    var l = (n: number, m: number): number => n * m / g(n, m)
    var ans = a[0]
    for (var i = 1; i < a.length; i++) {
        ans = l(ans, a[i])
    }
    return ans
}
function Math_lcmArray(val: number[]): number {
    var a = val
    var g = (n: number, m: number): number => m ? g(m, n % m) : n
    var l = (n: number, m: number): number => n * m / g(n, m)
    var ans = a[0]
    for (var i = 1; i < a.length; i++) {
        ans = l(ans, a[i])
    }
    return ans
}
function Math_primeList(val: number): number[] {
    var ans = [];
    var arr = new Array(val).fill(0);
    for (var i = 2; i < val; i++) {
        if (arr[i] == 0) {
            for (var j = i; j < val; j += i) {
                if (arr[j] == 0) arr[j] = i;
            }
        }
    }
    for (var i = 2; i < val; i++) {
        if (arr[i] == i) ans.push(i);
    }
    return ans;
}
function Math_primeFactor(p: number[], val: number): number[][] {
    var ans: number[][] = [];
    var valmax = val / 2;;
    for (var i = 0; i < p.length; i++) {
        var prime = p[i];
        if (valmax < prime) break;
        var cnt = 0;
        while (val % prime == 0) {
            val /= prime;
            cnt++;
        }
        if (cnt != 0) {
            ans.push([prime, cnt]);
        }
        if (val == 1) break;
    }
    return ans;
}

// union-find library
var g_uf_root: number[];
var g_uf_count: number[];
function UF_initRoot(num: number) {
    g_uf_root = new Array(num).fill(-1);
    g_uf_count = new Array(num).fill(1);
}
function UF_getRoot(idx: number) {
    if (g_uf_root[idx] < 0) {
        return idx;
    } else {
        var wrk0: number = UF_getRoot(g_uf_root[idx]);
        g_uf_root[idx] = wrk0;
        return wrk0
    }
}
function UF_mergeRoot(a: number, b: number) {
    var root0: number = UF_getRoot(a);
    var root1: number = UF_getRoot(b);
    if (root0 == root1) return;
    if (root0 > root1) [root0, root1] = [root1, root0];
    g_uf_count[root0] += g_uf_count[root1];
    g_uf_count[root1] = 0;
    g_uf_root[root1] = root0;
}

// entrypoint
function entrypoint() {
    try {
        var input = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        console.log("----");
        console.log("file='%s'", __filename.split("\\").slice(-1)[0]);
        console.log("----");
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            console.log("input=%o", input);
            console.time();
            console.log("----")
            main(input);
            console.log("----")
            console.timeEnd();
        });
    }
}
entrypoint();


// @ts-ignore
import * as fs from 'fs';
import { kMaxLength } from 'buffer';

// メイン
var g_root: number[];
var g_count: number[];

function main(input: string[]) {
    var work0: number[] = input.shift().split(" ").map(x => Number(x));
    var n: number = work0[0];
    var m: number = work0[1];
    var node: number[][] = input.map(x => x.split(" ").map(x => Number(x) - 1));
    g_root = new Array(n).fill(-1);
    g_count = new Array(n).fill(1);
    node.forEach(value => {
        var a: number = value[0];
        var b: number = value[1];
        var roota: number = getRoot(a);
        var rootb: number = getRoot(b);
        if (roota == rootb) return;
        if (roota > rootb) [roota, rootb] = [rootb, roota];
        mergeRoot(roota, rootb);
    });
    // TODO Math.max(...)は使ってはダメ、スプレッド構文はスタックに展開するのでスタックがあふれる
    // console.log(Math.max(g_cound));
    console.log(Math_max(g_count));
}

function Math_max(arr: number[]) {
    return arr.reduce(function(x, y) {
        return Math.max(x, y);
    });
}
function getRoot(index: number) {
    if (g_root[index] < 0) {
        return index;
    } else {
        var work0: number = getRoot(g_root[index]);
        g_root[index] = work0;
        return work0
    }
}

function mergeRoot(root0: number, root1: number) {
    g_count[root0] += g_count[root1];
    g_count[root1] = 0;
    g_root[root1] = root0;
}

// エントリポイント
// - OSによるパラメタの処理の違いを吸収
function entrypoint() {
    try {
        var input = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        console.log("----");
        console.log("file='%s'", __filename.split("\\").slice(-1)[0]);
        console.log("----");
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            console.log("input=%o", input);
            console.time();
            console.log("----")
            main(input);
            console.log("----")
            console.timeEnd();
        });
    }
}
entrypoint();


// @ts-ignore
import * as fs from 'fs';

// メイン
var g_root: number[];
var g_count: number[];

function main(input: string[]) {
    var work0: number[] = input.shift().split(" ").map(x => Number(x));
    var n: number = work0[0];
    var m: number = work0[1];
    var node: number[][] = input.map(x => x.split(" ").map(x => Number(x) - 1));
    g_root = new Array(n).fill(-1);
    g_count = new Array(n).fill(1);
    node.forEach(value => {
        var a: number = value[0];
        var b: number = value[1];
        var roota: number = getRoot(a);
        var rootb: number = getRoot(b);
        if (roota == rootb) return;
        if (roota > rootb) [roota, rootb] = [rootb, roota];
        mergeRoot(roota, rootb);
    });
    console.log(g_count.reduce(function(x, y) { return Math.max(x, y) }));
}

function getRoot(index: number) {
    if (g_root[index] < 0) {
        return index;
    } else {
        var work0: number = getRoot(g_root[index]);
        g_root[index] = work0;
        return work0
    }
}

function mergeRoot(root0: number, root1: number) {
    g_count[root0] += g_count[root1];
    g_count[root1] = 0;
    g_root[root1] = root0;
}

// エントリポイント
// - OSによるパラメタの処理の違いを吸収
function entrypoint() {
    try {
        var input = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        console.log("----");
        console.log("file='%s'", __filename.split("\\").slice(-1)[0]);
        console.log("----");
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            console.log("input=%o", input);
            console.time();
            console.log("----")
            main(input);
            console.log("----")
            console.timeEnd();
        });
    }
}
entrypoint();


// @ts-ignore
import * as fs from 'fs';
import { kMaxLength } from 'buffer';

// メイン
var g_root: number[];
var g_count: number[];

function main(input: string[]) {
    var work0: number[] = input.shift().split(" ").map(x => Number(x));
    var n: number = work0[0];
    var m: number = work0[1];
    var node: number[][] = input.map(x => x.split(" ").map(x => Number(x) - 1));
    g_root = new Array(n).fill(-1);
    g_count = new Array(n).fill(1);
    node.forEach(value => {
        var a: number = value[0];
        var b: number = value[1];
        var roota: number = getRoot(a);
        var rootb: number = getRoot(b);
        if (roota == rootb) return;
        if (roota > rootb) [roota, rootb] = [rootb, roota];
        mergeRoot(roota, rootb);
    });
    // TODO Math.max(...)は使ってはダメ、スプレッド構文はスタックに展開するのでスタックがあふれる
    // console.log(Math.max(g_cound));
    console.log(Math_max(g_count));
}

function Math_max(arr: number[]) {
    arr.reduce(function(x, y) {
        return Math.max(x, y);
    });
}
function getRoot(index: number) {
    if (g_root[index] < 0) {
        return index;
    } else {
        var work0: number = getRoot(g_root[index]);
        g_root[index] = work0;
        return work0
    }
}

function mergeRoot(root0: number, root1: number) {
    g_count[root0] += g_count[root1];
    g_count[root1] = 0;
    g_root[root1] = root0;
}

// エントリポイント
// - OSによるパラメタの処理の違いを吸収
function entrypoint() {
    try {
        var input = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        console.log("----");
        console.log("file='%s'", __filename.split("\\").slice(-1)[0]);
        console.log("----");
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            console.log("input=%o", input);
            console.time();
            console.log("----")
            main(input);
            console.log("----")
            console.timeEnd();
        });
    }
}
entrypoint();


// @ts-ignore
import * as fs from 'fs';

// メイン
var g_root: number[];
var g_count: number[];

function main(input: string[]) {
    var work0: number[] = input.shift().split(" ").map(x => Number(x));
    var n: number = work0[0];
    var m: number = work0[1];
    var node: number[][] = input.map(x => x.split(" ").map(x => Number(x) - 1));
    g_root = new Array(n).fill(-1);
    g_count = new Array(n).fill(1);
    node.forEach(value => {
        var a: number = value[0];
        var b: number = value[1];
        var roota: number = getRoot(a);
        var rootb: number = getRoot(b);
        if (roota == rootb) return;
        if (roota > rootb) [roota, rootb] = [rootb, roota];
        mergeRoot(roota, rootb);
    });
    console.log(Math.max(...g_count));
}

function getRoot(index: number) {
    if (g_root[index] < 0) {
        return index;
    } else {
        var work0: number = getRoot(g_root[index]);
        g_root[index] = work0;
        return work0
    }
}

function mergeRoot(root0: number, root1: number) {
    g_count[root0] += g_count[root1];
    g_count[root1] = 0;
    g_root[root1] = root0;
}

// エントリポイント
// - OSによるパラメタの処理の違いを吸収
function entrypoint() {
    try {
        var input = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        console.log("----");
        console.log("file='%s'", __filename.split("\\").slice(-1)[0]);
        console.log("----");
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            console.log("input=%o", input);
            console.time();
            console.log("----")
            main(input);
            console.log("----")
            console.timeEnd();
        });
    }
}
entrypoint();


// @ts-ignore
import * as fs from 'fs';

// メイン
var g_root: number[];
var g_count: number[];

function main(input: string[]) {
    var work0: number[] = input.shift().split(" ").map(x => Number(x));
    var n: number = work0[0];
    var m: number = work0[1];
    var node: number[][] = input.map(x => x.split(" ").map(x => Number(x) - 1));
    g_root = new Array(n).fill(-1);
    g_count = new Array(n).fill(1);
    node.forEach(value => {
        var a: number = value[0];
        var b: number = value[1];
        var roota: number = getRoot(a);
        var rootb: number = getRoot(b);
        if (roota == rootb) return;
        if (roota > rootb) [roota, rootb] = [rootb, roota];
        mergeRoot(roota, rootb);
    });
    console.log(Math.max(...g_count));
}

function getRoot(index: number) {
    if (g_root[index] < 0) {
        return index;
    } else {
        var work0: number = getRoot(g_root[index]);
        g_root[index] = work0;
        return work0
    }
}

function mergeRoot(root0: number, root1: number) {
    g_count[root0] += g_count[root1];
    g_count[root1] = 0;
    g_root[root1] = root0;
}

// エントリポイント
// - OSによるパラメタの処理の違いを吸収
function entrypoint() {
    try {
        var input = fs.readFileSync("/dev/stdin", "utf8").split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        console.log("----");
        console.log("file='%s'", __filename.split("\\").slice(-1)[0]);
        console.log("----");
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            console.log("input=%o", input);
            console.time();
            console.log("----")
            main(input);
            console.log("----")
            console.timeEnd();
        });
    }
}
entrypoint();


from itertools import accumulate
import sys
read = sys.stdin.buffer.read

def main():
  N, K, *p = map(int, read().split())
  p = [0] + list(accumulate(p))
  print((max(b - a for a, b in zip(p, p[K:])) + K) / 2)

if __name__ == '__main__':
    main()


from itertools import accumulate
import sys

def main():
  read = sys.stdin.buffer.read
  N, K, *p = map(int, read().split())
  p = [0] + list(accumulate(p))
  print((max(y - x for x, y in zip(p, p[K:])) + K) / 2)

if __name__ == '__main__':
    main()


from itertools import accumulate

def main():
    N, K= map(int, input().split())
    p = list(map(int, input().split()))
    # 累積和
    p = [0] + list(accumulate(p))

    # 累積和が最大になる区間、期待値は(1+p)/2、k個分なので以下の式。
    print((max(b - a for a, b in zip(p, p[K:])) + K) / 2)

if __name__ == '__main__':
  	main()

'''
5 3
1 2 2 4 5

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


def main():

    n, k = map(int, input().split())
    p = list(map(int, input().split()))

    ex = [0]
    for x in p:
        ex.append(ex[-1] + 1/x * (sum(list(range(1, x+1)))))

    ans = 0
    for i in range(k, n+1):
        ans = max(ans, ex[i] - ex[i-k])

    print(ans)

main()


n, k = map(int, input().split())
p = list(map(int, input().split()))

ex = [0]
for x in p:
    ex.append(ex[-1] + 1/x * (sum(list(range(1, x+1)))))

ans = 0
for i in range(k, n+1):
    ans = max(ans, ex[i] - ex[i-k])

print(ans)


n, k = map(int, input().split())
p = list(map(int, input().split()))

ex = []
for x in p:
    ex.append(1/x * (sum(list(range(1, x+1)))))

cs = [0]
for x in ex:
    cs.append(cs[-1]+x)

ans = 0
for i in range(k, n+1):
    ans = max(ans, cs[i] - cs[i-k])

print(ans)


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.*;

public class Main {
    static InputStream is;
    static PrintWriter out;
    static String INPUT = "";

    static void solve() {
        int num = ni();
        int k = ni();
        long p[] = new long[num];
        for (int i = 0; i < num; i++) {
            p[i] = nl();
        }
        double ps[] = new double[num + 1];
        for (int i = 0; i < num; i++) {
            ps[i + 1] = (p[i] + 1) * 0.5;
        }
        for (int i = 1; i <= num; i++) {
            ps[i] += ps[i - 1];
        }
        double max = 0;
        for (int i = 0; i + k <= num; i++) {
            max = Math.max(max, ps[i + k] - ps[i]);
        }
        out.println(max);
    }

    public static void main(String[] args) throws Exception {
        long S = System.currentTimeMillis();
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        out = new PrintWriter(System.out);

        solve();
        out.flush();
        long G = System.currentTimeMillis();
        tr(G-S+"ms");
    }

    private static boolean eof() {
        if(lenbuf == -1)return true;
        int lptr = ptrbuf;
        while(lptr < lenbuf)if(!isSpaceChar(inbuf[lptr++]))return false;

        try {
            is.mark(1000);
            while(true){
                int b = is.read();
                if(b == -1){
                    is.reset();
                    return true;
                }else if(!isSpaceChar(b)){
                    is.reset();
                    return false;
                }
            }
        } catch (IOException e) {
            return true;
        }
    }

    private static byte[] inbuf = new byte[1024];
    static int lenbuf = 0, ptrbuf = 0;

    private static int readByte() {
        if(lenbuf == -1)throw new InputMismatchException();
        if(ptrbuf >= lenbuf){
            ptrbuf = 0;
            try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
            if(lenbuf <= 0)return -1;
        }
        return inbuf[ptrbuf++];
    }

    private static boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }

    private static int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

    private static double nd() { return Double.parseDouble(ns()); }
    private static char nc() { return (char)skip(); }

    private static String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!(isSpaceChar(b))){
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private static char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while(p < n && !(isSpaceChar(b))){
            buf[p++] = (char)b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private static char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for(int i = 0;i < n;i++)map[i] = ns(m);
        return map;
    }

    private static int[] na(int n) {
        int[] a = new int[n];
        for(int i = 0;i < n;i++)a[i] = ni();
        return a;
    }

    private static int ni() {
        int num = 0, b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private static long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private static void tr(Object... o) { if(INPUT.length() != 0)System.out.println(Arrays.deepToString(o)); }

    // Union-Find
    // https://algs4.cs.princeton.edu/15uf/UF.java.html
    public static class UnionFind {
        private int count = 0;
        private int[] parent, rank;

        public UnionFind(int n) {
            count = n;
            parent = new int[n];
            rank = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        public int find(int p) {
            while (p != parent[p]) {
                parent[p] = parent[parent[p]];
                p = parent[p];
            }
            return p;
        }

        public void union(int p, int q) {
            int rootP = find(p);
            int rootQ = find(q);
            if (rootP ==rootQ) return;
            if (rank[rootQ] > rank[rootP]) {
                parent[rootP] = rootQ;
            } else {
                parent[rootQ] = rootP;
                if (rank[rootP] == rank[rootQ]) {
                    rank[rootP]++;
                }
            }
            count--;
        }

        public int count() {
            return count;
        }

        public void print() {
            out.println("Parent:");
            for (int i : parent) {
                out.print(i);
                out.print(" ");
            }
            out.println();
            out.println("Rank:");
            for (int i : rank) {
                out.print(i);
                out.print(" ");
            }
            out.println();
        }
    }

    // Dijkstra
    // Return min distance from start to end O(ElogV) (negative cost is prohibited)
    // edge is int[3] array {from,to,cost}
    // edges is edge list from specific node
    // all_edges is Map<from node number,edges>
    static int dijkstra(Map<Integer,List<int[]>> all_edges,int start,int end,int max_node_number) {
        int[] distance = new int[max_node_number + 1];
        Arrays.fill(distance, -1);
        PriorityQueue<int[]> p_que = new PriorityQueue<>((a,b) -> ((distance[a[0]] + a[2]) - (distance[b[0]] + b[2])));
        distance[start] = 0;
        List<int[]> edges = all_edges.get(start);
        p_que.addAll(edges);
        while (distance[end] < 0) {
            int[] nearest_edge = p_que.poll();
            assert nearest_edge != null;
            if (distance[nearest_edge[1]] < 0) {
                distance[nearest_edge[1]] = distance[nearest_edge[0]] + nearest_edge[2];
                if (all_edges.containsKey(nearest_edge[1])) {
                    edges = all_edges.get(nearest_edge[1]);
                    for (int[] edge : edges) {
                        if (distance[edge[1]] < 0) p_que.add(edge);
                    }
                }
            }
        }
        return distance[end];
    }

    // Enumerate primes in [2, n] with O(n log log n)
    public static List<Integer> sieveOfEratosthenes(int n) {
        boolean[] isPrime = new boolean[n+1];
        Arrays.fill(isPrime, true);
        for (int i = 2; i * i <= n; i++) {
            if (isPrime[i]) {
                for (int j = i + i; j <= n; j += i) {
                    isPrime[j] = false;
                }
            }
        }
        List<Integer> primes = new ArrayList<>();
        for (int i = 2; i <= n; i++) {
            if (isPrime[i]) {
                primes.add(i);
            }
        }
        return primes;
    }

    // Count divisor
    public static int countDivisor(int n) {
        int[] list = new int[n + 1];
        Arrays.fill(list, 0);
        int num = n;
        for (int i = 2; i <= n; i++) {
            while (num % i == 0) {
                list[i] = list[i] + 1;
                num /= i;
            }
        }
        int ans = 1;
        for (int i : list) {
            ans *= (i + 1);
        }
        return ans;
    }
}


import java.io.*;
import java.util.*;
import java.math.*;
// import java.awt.Point;

public class Main {
    InputStream is;
    PrintWriter out;
    String INPUT = "";

    static int mod = 1_000_000_007;
    // int mod = 998244353;
    // long inf = Long.MAX_VALUE/2;
    int inf = Integer.MAX_VALUE/2;

    void solve(){
        int n = ni();
        int k = ni();
        long[] p = new long[n];
        for(int i = 0; i < n; i++){
            p[i] = nl()+1;
        }
        long[] cum = new long[n+1];
        for(int i = 0; i < n; i++){
            cum[i+1] = cum[i] + p[i];
        }
        long sum = 0;
        for(int i = k; i <= n; i++){
            long val = cum[i] - cum[i-k];
            sum = Math.max(sum,val);
        }
        out.println((double)sum/2);
    }

    void run() throws Exception
    {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        out = new PrintWriter(System.out);
        long s = System.currentTimeMillis();
        solve();
        out.flush();
        if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");
    }

    public static void main(String[] args) throws Exception { new Main().run(); }

    private byte[] inbuf = new byte[1024];
    private int lenbuf = 0, ptrbuf = 0;

    private int readByte()
    {
        if(lenbuf == -1)throw new InputMismatchException();
        if(ptrbuf >= lenbuf){
            ptrbuf = 0;
            try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
            if(lenbuf <= 0)return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
    private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

    private double nd() { return Double.parseDouble(ns()); }
    private char nc() { return (char)skip(); }

    private String ns()
    {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!(isSpaceChar(b) && b != ' ')){
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n)
    {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while(p < n && !(isSpaceChar(b))){
            buf[p++] = (char)b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m)
    {
        char[][] map = new char[n][];
        for(int i = 0;i < n;i++)map[i] = ns(m);
        return map;
    }

    private int[] na(int n)
    {
        int[] a = new int[n];
        for(int i = 0;i < n;i++)a[i] = ni();
        return a;
    }

    private int ni()
    {
        int num = 0, b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl()
    {
        long num = 0;
        int b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private static void tr(Object... o) { System.out.println(Arrays.deepToString(o)); }

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author KharYusuf
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastReader in = new FastReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DDiceInLine solver = new DDiceInLine();
        solver.solve(1, in, out);
        out.close();
    }

    static class DDiceInLine {
        public void solve(int testNumber, FastReader s, PrintWriter w) {
            int n = s.nextInt(), k = s.nextInt();
            double ans, cur = 0;
            int[] p = new int[n];
            for (int i = 0; i < n; i++) p[i] = s.nextInt();
            for (int i = 0; i < k; i++) cur += (p[i] + 1) / 2.0;
            ans = cur;
            for (int i = k; i < n; i++) {
                cur -= (p[i - k] + 1) / 2.0;
                cur += (p[i] + 1) / 2.0;
                ans = Math.max(ans, cur);
            }
            w.println(ans);
        }

    }

    static class FastReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private FastReader.SpaceCharFilter filter;

        public FastReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {

            if (numChars == -1)
                throw new InputMismatchException();

            if (curChar >= numChars) {

                curChar = 0;

                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }

                if (numChars <= 0)
                    return -1;
            }

            return buf[curChar++];
        }

        public int nextInt() {

            int c = read();

            while (isSpaceChar(c))
                c = read();

            int sgn = 1;

            if (c == '-') {
                sgn = -1;
                c = read();
            }

            int res = 0;

            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();

                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));

            return res * sgn;
        }

        public boolean isSpaceChar(int c) {

            if (filter != null)
                return filter.isSpaceChar(c);

            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k= sc.nextInt();
        double[] p = new double[n];
        for (int i = 0; i < n; i++) {
            p[i] = sc.nextDouble();
        }
        double ans = 0.0;

        for (int i = 0; i < n - k + 1; i++) {
            double sum = 0.0;
            for (int j = i; j < i + k; j++) {
                double tmp = (p[j] + 1.0) / 2.0;
                sum += tmp;
            }
            ans = Math.max(ans, sum);
        }
        System.out.println(ans);
    }
}


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k= sc.nextInt();
        double[] p = new double[n];
        for (int i = 0; i < n; i++) {
            p[i] = sc.nextDouble();
        }
        double max = 0.0;
        int index = 0;
        for (int i = 0; i < n - k + 1; i++) {
            double sum = 0.0;
            for (int j = i; j < i + k; j++) {
                sum += p[j];
            }
            if(sum > max) {
                index = i;
                max = sum;
            }
        }
        double ans = 0.0;
        for (int i = index; i < index + k; i++) {
            double tmp = (p[i] + 1.0) / 2.0;
            ans += tmp;
        }
        System.out.println(ans);
    }
}


import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		double[] ave = new double[n];

		for (int i = 0; i < n; i++) {
			int roll = sc.nextInt();
			ave[i] = (double) (roll + 1) / 2;
		}

		double sum = 0;
		for (int i = 0; i < k; i++) {
			sum += ave[i];
		}
		double max = 0;

		for (int i = 0; i < n - k; i++) {
			sum = sum - ave[i] + ave[i + k];
			max = Math.max(max, sum);
		}

		System.out.println(max);

	}

}


#pragma GCC optimize ("O3")
#pragma GCC target ("avx")
//#include<bits/stdc++.h>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define rep1(i, n) for(int i = 1; i <= (n); i++)
#define co(x) cout << (x) << "\n"
#define cosp(x) cout << (x) << " "
#define ce(x) cerr << (x) << "\n"
#define cesp(x) cerr << (x) << " "
#define pb push_back
#define mp make_pair
#define chmin(x, y) x = min(x, y)
#define chmax(x, y) x = max(x, y)
#define Would
#define you
#define please

const int cm = 1 << 17;
char cn[cm], * ci = cn + cm, ct;
inline char getcha() {
	if (ci - cn == cm) { fread_unlocked(cn, 1, cm, stdin); ci = cn; }
	return *ci++;
}
inline int getint() {
	int A = 0;
	if (ci - cn + 16 > cm) while ((ct = getcha()) >= '0') A = A * 10 + ct - '0';
	else while ((ct = *ci++) >= '0') A = A * 10 + ct - '0';
	return A;
}

int main() {
	//cin.tie(0);
	//ios::sync_with_stdio(false);

	int N = getint(), K = getint();
	int P[200001];

	ll saidai = 0;
	ll ima = K;
	rep(i, K) {
		P[i] = getint();
		ima += P[i];
	}
	saidai = ima;

	int k = 0;
	for (int i = K; i < N; i++, k++) {
		if (k == K) k = 0;
		ima -= P[k];
		P[k] = getint();
		ima += P[k];
		chmax(saidai, ima);
	}

	double kotae = saidai * 0.5;

	printf("%.6f", kotae);

	Would you please return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#define REP(i,a,b) for(register int i=(a); i<(b); i++)
#define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
#define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
using namespace std;
typedef long long ll;
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template <class T> inline void read(T&x) {
	x=0; char ch; do ch=getchar(); while(ch<=' ');
	while(ch>' ') {x=x*10+ch-'0'; ch=getchar();}
}
#define MAXN 200007
int n,k;
int p[MAXN];
int main() {
	read(n); read(k);
	REP(i,0,n) {read(p[i]); p[i]++;}
	REP(i,1,n) p[i]+=p[i-1];
	PERE(i,n-1,k) p[i]-=p[i-k];
	int ans=0;
	REP(i,k-1,n) {
		ans = max(ans, p[i]);
	}
	printf("%lf\n", ans/2.0);
	return 0;
}


#include <bits/stdc++.h>

class kin{
public:
	inline void open(FILE *,int);
	inline void close(void);
	inline void scan(void);
	inline kin &operator>(char &);
	inline kin &operator>(int &);
	inline kin &operator>(long long &);
	inline kin &operator>(double &);
	inline kin &operator>(long double &);
	inline kin &operator>(char *);
	template<class T>
	inline void get(T *,int);
private:
	FILE *fp;
	char *buf;
	int siz;
	int idx;
}in;

class kout{
public:
	inline void open(FILE *,int);
	inline void close(void);
	inline void print(void);
	inline kout &operator<(char);
	inline kout &operator<(int);
	inline kout &operator<(long long);
	inline kout &operator<(double);
	inline kout &operator<(long double);
	inline kout &operator<(const char *);
	template<class T>
	inline void put(T *,int,char,char);
private:
	FILE *fp;
	char *buf;
	int siz;
	int idx;
}out;

inline void chmax(long long val,long long &var){
	if(val>var) var=val;
}

int main(int argc,char **argv){
	in.open(stdin,512);
	out.open(stdout,512);
	in.scan();
	int n,k;
	in>n>k;
	long long d[200001];
	d[0]=0LL;
	for(int i=1;i<=n;++i){
		long long p;
		in>p;
		d[i]=d[i-1]+p+1LL;
	}
	long long ans=d[k];
	for(int i=k+1;i<=n;++i) chmax(d[i]-d[i-k],ans);
	out<(long double)ans/2.0L<'\n';
	out.print();
	in.close();
	out.close();
	return 0;
}

inline void kin::open(FILE *fparg,int sizarg){
	fp=fparg;
	buf=new char[sizarg];
	siz=sizarg;
	idx=0;
	return;
}
inline void kin::close(void){
	fp=nullptr;
	delete[] buf;
	buf=nullptr;
	siz=0;
	idx=0;
	return;
}
inline void kin::scan(void){
	int readsiz=(int)std::fread((void *)buf,(std::size_t)1,(std::size_t)siz,fp);
	if(readsiz!=siz) buf[readsiz]='\x00';
	idx=0;
	return;
}
inline kin &kin::operator>(char &var){
	if(!buf[idx]){
		var='\x00';
		return *this;
	}
	var=buf[idx];
	if(++idx==siz) scan();
	if(++idx==siz) scan();
	return *this;
}
inline kin &kin::operator>(int &var){
	if(!buf[idx]){
		var=0;
		return *this;
	}
	int sign=-1;
	if(buf[idx]=='-'){
		sign=1;
		if(++idx==siz) scan();
	}
	var=0;
	while(buf[idx]>='0'){
		var=var*10-(int)(buf[idx]-'0');
		if(++idx==siz) scan();
	}
	var*=sign;
	if(++idx==siz) scan();
	return *this;
}
inline kin &kin::operator>(long long &var){
	if(!buf[idx]){
		var=0LL;
		return *this;
	}
	long long sign=-1LL;
	if(buf[idx]=='-'){
		sign=1LL;
		if(++idx==siz) scan();
	};
	var=0LL;
	while(buf[idx]>='0'){
		var=var*10LL-(long long)(buf[idx]-'0');
		if(++idx==siz) scan();
	}
	var*=sign;
	if(++idx==siz) scan();
	return *this;
}
inline kin &kin::operator>(double &var){
	if(!buf[idx]){
		var=0.0;
		return *this;
	}
	double sign=-1.0;
	if(buf[idx]=='-'){
		sign=1.0;
		if(++idx==siz) scan();
	}
	var=0.0;
	while(buf[idx]>='0'){
		var=var*10.0-(double)(buf[idx]-'0');
		if(++idx==siz) scan();
	}
	if(buf[idx]=='.'){
		if(++idx==siz) scan();
		double dig=1.0;
		while(buf[idx]>='0'){
			var-=(double)(buf[idx]-'0')*(dig/=10.0);
			if(++idx==siz) scan();
		}
	}
	var*=sign;
	if(++idx==siz) scan();
	return *this;
}
inline kin &kin::operator>(long double &var){
	if(!buf[idx]){
		var=0.0L;
		return *this;
	}
	long double sign=-1.0L;
	if(buf[idx]=='-'){
		sign=1.0L;
		if(++idx==siz) scan();
	}
	var=0.0L;
	while(buf[idx]>='0'){
		var=var*10.0L-(long double)(buf[idx]-'0');
		if(++idx==siz) scan();
	}
	if(buf[idx]=='.'){
		if(++idx==siz) scan();
		long double dig=1.0L;
		while(buf[idx]>='0'){
			var-=(long double)(buf[idx]-'0')*(dig/=10.0L);
			if(++idx==siz) scan();
		}
	}
	var*=sign;
	if(++idx==siz) scan();
	return *this;
}
inline kin &kin::operator>(char *str){
	if(!buf[idx]){
		str[0]='\x00';
		return *this;
	}
	int ptr=0;
	while(buf[idx]>='!'){
		str[ptr++]=buf[idx];
		if(++idx==siz) scan();
	}
	str[ptr]='\x00';
	if(++idx==siz) scan();
	return *this;
}
template<class T>
inline void kin::get(T *arr,int num){
	for(int i=0;i<num;++i) (*this)>arr[i];
	return;
}

inline void kout::open(FILE *fparg,int sizarg){
	fp=fparg;
	buf=new char[sizarg];
	siz=sizarg;
	idx=0;
	return;
}
inline void kout::close(void){
	fp=nullptr;
	delete[] buf;
	buf=nullptr;
	siz=0;
	idx=0;
	return;
}
inline void kout::print(void){
	std::fwrite((void *)buf,(std::size_t)1,(std::size_t)idx,fp);
	idx=0;
	return;
}
inline kout &kout::operator<(char val){
	buf[idx]=val;
	if(++idx==siz) print();
	return *this;
}
inline kout &kout::operator<(int val){
	if(val<0){
		buf[idx]='-';
		if(++idx==siz) print();
	}
	else val*=-1;
	char dig[10];
	int ptr=0;
	do{
		int tmp=val/10;
		dig[ptr++]=(char)-(val-tmp*10)+'0';
		val=tmp;
	}while(val);
	while(ptr--){
		buf[idx]=dig[ptr];
		if(++idx==siz) print();
	}
	return *this;
}
inline kout &kout::operator<(long long val){
	if(val<0LL){
		buf[idx]='-';
		if(++idx==siz) print();
	}
	else val*=-1LL;
	char dig[19];
	int ptr=0;
	do{
		long long tmp=val/10LL;
		dig[ptr++]=(char)-(val-tmp*10LL)+'0';
		val=tmp;
	}while(val);
	while(ptr--){
		buf[idx]=dig[ptr];
		if(++idx==siz) print();
	}
	return *this;
}
inline kout &kout::operator<(double val){
	if(val<0.0){
		buf[idx]='-';
		if(++idx==siz) print();
	}
	else val*=-1.0;
	double dig=1.0;
	while(val/dig<=-10.0) dig*=10.0;
	int tmp;
	while(dig>=1.0){
		buf[idx]=(char)-(tmp=(int)(val/dig))+'0';
		if(++idx==siz) print();
		val-=(double)tmp*dig;
		dig/=10.0;
	}
	buf[idx]='.';
	if(++idx==siz) print();
	for(int i=0;i<12;++i){
		buf[idx]=(char)-(tmp=(int)(val/dig))+'0';
		if(++idx==siz) print();
		val-=(double)tmp*dig;
		dig/=10.0;
	}
	return *this;
}
inline kout &kout::operator<(long double val){
	if(val<0.0L){
		buf[idx]='-';
		if(++idx==siz) print();
	}
	else val*=-1.0L;
	long double dig=1.0L;
	while(val/dig<=-10.0L) dig*=10.0L;
	int tmp;
	while(dig>=1.0L){
		buf[idx]=(char)-(tmp=(int)(val/dig))+'0';
		if(++idx==siz) print();
		val-=(long double)tmp*dig;
		dig/=10.0L;
	}
	buf[idx]='.';
	if(++idx==siz) print();
	for(int i=0;i<16;++i){
		buf[idx]=(char)-(tmp=(int)(val/dig))+'0';
		if(++idx==siz) print();
		val-=(long double)tmp*dig;
		dig/=10.0L;
	}
	return *this;
}
inline kout &kout::operator<(const char *str){
	for(int i=0;str[i];++i){
		buf[idx]=str[i];
		if(++idx==siz) print();
	}
	return *this;
}
template<class T>
inline void kout::put(T *arr,int num,char dlm,char end){
	--num;
	for(int i=0;i<num;++i) (*this)<arr[i]<dlm;
	(*this)<arr[num]<end;
	return;
}


#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,k;
    cin >> n >> k;
    vector<int> kitai(n),dp(n-k+1);
    double ans=0;
    for(int i=0;i<n;i++){
        int a;
        cin >> a;
        kitai.at(i)=(a+1);
    }
    for(int i=0;i<k;i++){
        dp.at(0)+=kitai.at(i);
    }
    ans=dp.at(0);
    if(n-k+1!=1){
        for(int i=1;i<n-k+1;i++){
            dp.at(i)=dp.at(i-1)+kitai.at(i+k-1)-kitai.at(i-1);
            if(ans<dp.at(i))ans=dp.at(i);
        }
    }
    cout << (double)ans/2 << endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,k;
    cin >> n >> k;
    vector<double> kitai(n),dp(n-k+1);
    double ans=0;
    for(int i=0;i<n;i++){
        int a;
        cin >> a;
        kitai.at(i)=(double)(a+1)/(double)2;
    }
    for(int i=0;i<k;i++){
        dp.at(0)+=kitai.at(i);
    }
    ans=dp.at(0);
    if(n-k+1!=1){
        for(int i=1;i<n-k+1;i++){
            dp.at(i)=dp.at(i-1)+kitai.at(i+k-1)-kitai.at(i-1);
            if(ans<dp.at(i))ans=dp.at(i);
        }
    }
    cout << ans << endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,k;
    cin >> n >> k;
    vector<double> kitai(n),dp(n-k+1);
    double ans=0;
    for(int i=0;i<n;i++){
        int a;
        cin >> a;
        kitai.at(i)=(double)(a+1)/(double)2;
    }
    for(int i=0;i<k;i++){
        dp.at(0)+=kitai.at(i);
    }
    ans=dp.at(0);
    for(int i=1;i<n-k+1;i++){
        dp.at(i)=dp.at(i-1)+kitai.at(i+k-1)-kitai.at(i-1);
        if(ans<dp.at(i))ans=dp.at(i);
    }
    cout << ans << endl;
    return 0;
}


// ABC 154-D
// 2020.2.9 bal4u

#include <stdio.h>

typedef long long ll;

#define gc() getchar_unlocked()

int in() {   // 非負整数の入力
	int n = 0; int c;
	c = gc();
	do n = 10 * n + (c & 0xf); while ((c = gc()) >= '0');
	return n;
}

int s[200005];

int main()
{
	int i, K, N, ans;

	N = in(), K = in();
	for (i = 1; i <= N; ++i) s[i] = s[i-1] + (in()+1);

	ans = 0;
	for (i = K; i <= N; ++i) {
		if (s[i]-s[i-K] > ans) ans = s[i]-s[i-K];
	}
	printf("%.10lf\n", 0.5*ans);
	return 0;
}


char buf[1<<20];
int p[2<<17];
int N,K;
int sz;
int ans;
main()
{
	read(0,buf,1<<20);
	for(;;)
	{
		char k=buf[sz++];
		if(k<'0')break;
		N=N*10+k-'0';
	}
	for(;;)
	{
		char k=buf[sz++];
		if(k<'0')break;
		K=K*10+k-'0';
	}
	for(int i=0;i<N;i++)
	{
		for(;;)
		{
			char k=buf[sz++];
			if(k<'0')break;
			p[i]=p[i]*10+k-'0';
		}
	}
	for(int i=1;i<N;i++)p[i]+=p[i-1];
	for(int i=N-1;i>=K;i--)
	{
		p[i]-=p[i-K];
	}
	for(int i=0;i<N;i++)
    {
		if(ans<p[i])ans=p[i];
    }
	printf("%f\n",(ans+K)/2.);
}


// ABC 154-D
// 2020.2.9 bal4u

#include <stdio.h>

typedef long long ll;

#define gc() getchar_unlocked()

int in() {   // 非負整数の入力
	int n = 0; int c;
	c = gc();
	do n = 10 * n + (c & 0xf); while ((c = gc()) >= '0');
	return n;
}

int s[200005];
int a[200005];

int main()
{
	int i, K, N;
	int ma, ii;
	double ans;

	N = in(), K = in();
	for (i = 1; i <= N; ++i) {
		a[i] = in() + 1;
		s[i] = s[i-1] + a[i];
	}
	ma = 0;
	for (i = K; i <= N; ++i) {
		if (s[i]-s[i-K] > ma) {
			ma = s[i]-s[i-K], ii = i-K;
		}
	}
	ans = 0;
	for (i = 1; i <= K; ++i) ans += a[i+ii]*0.5;
	printf("%.10lf\n", ans);
	return 0;
}


#include<stdio.h>

int main()
{

	long int n,k,i,j;
  long double p[200001],max,sum;
  sum=0;
  max=0;
(void) scanf("%ld %ld",&n,&k);

  for (i=1;i<=n;i++)
  {
(void) scanf("%llf",&p[i]);
   p[i]=(p[i]+1)/2;
  }

  for (i=1;i<=k;i++)
  {
  	sum+=p[i];
  }

  //printf("%llf\n",sum);

  for (i=k+1;i<=n;i++)
   {
   sum=sum+p[i];
   sum=sum-p[i-k];
    //printf("%llf %llf %llf \n",p[i],p[i-k],sum);
    if (sum>max)
    {
    	max=sum;
    }
   }

  /*
  for (i=1;i<=n-k+1;i++)
  {
  	for (j=1;j<=k;j++)
    {
    	sum+=p[i+j-1];
    }
    	if (sum>max)
        {
        	max=sum;
        }
    sum=0.0;
  }
*/

  printf("%llf",max);
  return 0;

}


#include<stdio.h>

int main()
{

	long int n,k,i,j;
  long double p[200001],max,sum;
  sum=0;
  max=0;
(void) scanf("%ld %ld",&n,&k);

  for (i=1;i<=n;i++)
  {
(void) scanf("%llf",&p[i]);
   p[i]=(p[i]+1)/2;
  }

  for (i=1;i<=n-k+1;i++)
  {
  	sum+=p[i];
  }

  //printf("%llf\n",max);

  for (i=n-k+2;i<=n;i++)
   {
   sum=sum+p[i];
   sum=sum-p[i-k];
    //printf("%llf %llf %llf \n",p[i],p[i-k],sum);
    if (sum>max)
    {
    	max=sum;
    }
   }

  /*
  for (i=1;i<=n-k+1;i++)
  {
  	for (j=1;j<=k;j++)
    {
    	sum+=p[i+j-1];
    }
    	if (sum>max)
        {
        	max=sum;
        }
    sum=0.0;
  }
*/

  printf("%llf",max);
  return 0;

}


#include<stdio.h>

int main()
{

	long int n,k,i,j;
  long double p[200001],max,sum;
  sum=0;
  max=0;
(void) scanf("%ld %ld",&n,&k);

  for (i=1;i<=n;i++)
  {
(void) scanf("%lf",&p[i]);
   p[i]=(p[i]+1)/2;
  }

  for (i=1;i<=n-k+1;i++)
  {
  	for (j=1;j<=k;j++)
    {
    	sum+=p[i+j-1];
    }
    	if (sum>max)
        {
        	max=sum;
        }
    sum=0.0;
  }

  printf("%lf",max);
  return 0;

}


function Main(input) {
	input = input.split("\n");
	input[0] = input[0].split(' ');
	input[1] = input[1].split(' ');
	var sum = new Array(input[0][0] - input[0][1] + 1);
	for(var i=0; i<2; i++){
    	input[0][i] = parseInt(input[0][i], 10);
    }
  var sig = 0;
	var max = 0;
	var maxN = 0;
	for(var i=0; i<input[0][0]; i++){
    	input[1][i] = parseInt(input[1][i], 10);
    	input[1][i] = (input[1][i]+1)/2;
    	sig += input[1][i];
        if(i >= input[0][1] - 1){
        	sum[i-input[0][1]+1] = sig;
        	sig -= input[1][i-input[0][1]+1];
        	if(max < sum[i-input[0][1]+1]){
       			max = sum[i-input[0][1]+1];
        		maxN = i-input[0][1]+1;
        	}
        }
    }
	console.log(sum[maxN]);
}
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


console.log((args=>{
  const [[N,K],p] = args.trim().split`\n`.map(r=>r.split` `.map(v=>0|v));
  const s = [0];
  for ( let i = 0; i < N; i++ ) s.push( s[i] + p[i] + 1 );
  let max = 0;
  for ( let i = 0; i + K <= N; i++ ) if ( max < s[i+K] - s[i] ) max = s[i+K] - s[i];
  return `${max/2}`;
})(require('fs').readFileSync('/dev/stdin', 'utf8')));


function Main(input) {
  input = input.trim().split("\n").map(function(x) { return x.split(" ")});
  var L1 = input[0].map(e => parseInt(e, 10));
  var N = L1[0];
  var K = L1[1];
  var vec_p = input[1].map(e => parseInt(e, 10));
  var tmpSum = 0;
  var tmpSet = [];
  var changed, ans;
  for (var i = 0; i < K; i++){
    tmpSum += vec_p[i];
    tmpSet.push(vec_p[i]);
  }
  ans = tmpSum;
  for (var i = K; i < N; i++){
    changed = i % K;
    tmpSum += (vec_p[i] - tmpSet[changed]);
    tmpSet[changed] = vec_p[i];
    if (tmpSum > ans) ans = tmpSum;
  }
  ans = (ans + K) / 2;
  console.log(ans);
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function Main(input) {
  input=input.split("\n");
  if(input[input.length-1]===''){
    input.pop();
  }
  const N=input[0].split(' ')[0]-0;
  const K=input[0].split(' ')[1]-0;
  const value=input[1].split(' ').map(e=>{
    return (e-0+1)/2;
  });
  var sum=0;
  var max;
  for(var i=0;i<K;i++){
    sum+=value[i];
  }
  max=sum;
  for(var i=0;i<N-K;i++){
    sum+=value[K+i]-value[i];
    if(max<sum){
      max=sum;
    }
  }
  console.log(sum);
}

//*この行以降は編集しないでください（標準入出力から一度に読み込み、Mainを呼び出します）
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function Main(input){
    const arr = input.split('\n');
    const [N, K] = arr[0].split(' ').map(Number);
    const pi = arr[1].split(' ').map(Number);
    let maxNum = 0;
    let Knum = 0;
    let answer = 0;
    for(let i=0; i<K; i++){
        Knum += pi[i];
    }
    maxNum = Knum;
    for(let i=K; i<pi.length; i++){
        Knum += pi[i]-pi[i-K];
        if(maxNum < Knum)  maxNum = Knum;
    }
    const answer = (maxNum+K)/2;
    console.log(answer);
}
Main(require("fs").readFileSync("/dev/stdin", "utf8").trim());


// ProblemURL: https://atcoder.jp/contests/abc154/tasks/abc154_d
// --------------------------------------------------------

package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"sort"
	"strconv"
	"strings"
)

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
func diff(a, b int) int {
	if a > b {
		return a - b
	}
	return b - a
}
func larger(a, b int) int {
	if a > b {
		return a
	}
	return b
}
func smaller(a, b int) int {
	if a < b {
		return a
	}
	return b
}
func largest(a, b, c int) int {
	var x int
	if a > b {
		x = a
	} else {
		x = b
	}
	if c > x {
		x = c
	}
	return x
}
func smallest(a, b, c int) int {
	var x int
	if a < b {
		x = a
	} else {
		x = b
	}
	if c < x {
		x = c
	}
	return x
}
func intsMax(a []int) (val int) {
	if len(a) == 0 {
		panic("func intsMax: zero length slice")
	}
	val = a[0]
	for _, aa := range a {
		if aa > val {
			val = aa
		}
	}
	return
}
func intsMaxIdx(a []int) (idx, val int) {
	if len(a) == 0 {
		panic("func intsMaxIdx: zero length slice")
	}
	val = a[0]
	for i, aa := range a {
		if aa > val {
			idx, val = i, aa
		}
	}
	return
}
func intsMin(a []int) (val int) {
	if len(a) == 0 {
		panic("func intsMin: zero length slice")
	}
	val = a[0]
	for _, aa := range a {
		if aa < val {
			val = aa
		}
	}
	return
}
func intsMinIdx(a []int) (idx, val int) {
	if len(a) == 0 {
		panic("func intsMinIdx: zero length slice")
	}
	val = a[0]
	for i, aa := range a {
		if aa < val {
			idx, val = i, aa
		}
	}
	return
}
func intsSum(a []int) int {
	res := 0
	for _, v := range a {
		res += v
	}
	return res
}
func intsMul(a []int) int {
	res := 1
	for _, v := range a {
		res *= v
	}
	return res
}
func intsAve(s []int) float64 {
	return float64(intsSum(s)) / float64(len(s))
}
func intsAdd(a *[]int, x int)       { *a = append(*a, x) }
func intsDelete(a *[]int, i int)    { *a = append((*a)[:i], (*a)[i+1:]...) }
func intsJoin(a, b []int) []int     { return append(a, b...) }
func intsClear(a []int) []int       { return a[:0] }
func intsCopy(a []int) []int        { return append([]int(nil), a...) }
func intsCopySortAsc(a []int) []int { s := intsCopy(a); sort.Ints(s); return s }
func intsCopySortDesc(a []int) []int {
	s := intsCopy(a)
	sort.Sort(sort.Reverse(sort.IntSlice(s)))
	return s
}
func intsReverse(a []int) {
	for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
		a[i], a[j] = a[j], a[i]
	}
}
func intsFill(a []int, val int) {
	for i := 0; i < len(a); i++ {
		a[i] = val
	}
}
func intsPeekBack(a []int) int {
	if len(a) == 0 {
		panic("func peekBack: zero length slice")
	}
	return a[len(a)-1]
}
func intsPeekFront(a []int) int {
	if len(a) == 0 {
		panic("func peekFront: zero length slice")
	}
	return a[0]
}
func intsPopBack(a *[]int) int {
	if len(*a) == 0 {
		panic("func popBack: zero length slice")
	}
	t := (*a)[len(*a)-1]
	*a = (*a)[:len(*a)-1]
	return t
}
func intsPopFront(a *[]int) int {
	if len(*a) == 0 {
		panic("func popFront: zero length slice")
	}
	h := (*a)[0]
	*a = (*a)[1:]
	return h
}
func intsPushBack(a *[]int, x int) { *a = append(*a, x) }
func intsPushFront(a *[]int, x int) {
	*a = append(*a, 0)
	copy((*a)[1:], (*a)[0:])
	(*a)[0] = x
}
func intsAppendSentinelHead(a *[]int, sentinel int) { intsPushFront(a, sentinel) }
func intsAppendSentinelTail(a *[]int, sentinel int) { intsPushBack(a, sentinel) }
func intsAppendSentinels(a *[]int, sentinel int) {
	intsPushFront(a, sentinel)
	intsPushBack(a, sentinel)
}
func intsIota(first, size int) []int {
	as := make([]int, size)
	for i := range as {
		as[i] = first + i
	}
	return as
}
func intsHaveDuplicateElm(a []int) bool {
	m := make(map[int]bool, len(a))
	for _, aa := range a {
		if _, exists := m[aa]; exists {
			return true
		} else {
			m[aa] = true
		}
	}
	return false
}
func isEven(n int) bool         { return n&1 == 0 }
func isOdd(n int) bool          { return n&1 == 1 }
func floor(x float64) int       { return int(x) }
func ceil(x float64) int        { return int(math.Ceil(x)) }
func ceilDiv(x, y int) int      { return ((x) + (y) - 1) / (y) }
func floorDiv(x, y int) int     { return (x) / (y) }
func floatDiv(x, y int) float64 { return float64(x) / float64(y) }
func pow(x, y int) int {
	if y < 0 {
		panic("Exponent must be a natural number")
	}
	z := 1
	for ; y != 0; y >>= 1 {
		if y&1 == 1 {
			z *= x
		}
		x *= x
	}
	return z
}
func fact(x int) int {
	fact := 1
	for i := 1; i <= x; i++ {
		fact *= i
	}
	return fact
}
func sigmaK(n int) int  { return n * (n + 1) / 2 }
func sigmaKK(n int) int { return (n * (n + 1) / 2) * (2*n + 1) / 3 }
func euclideanDistance(a, b point) float64 {
	s := diff(a.x, b.x)
	s *= s
	t := diff(a.y, b.y)
	t *= t
	return math.Sqrt(float64(s) + float64(t))
}
func manhattanDistance(a, b point) int {
	s := diff(a.x, b.x)
	t := diff(a.y, b.y)
	return s + t
}
func swap(a, b *int) { *a, *b = *b, *a }
func chmax(a *int, b int) bool {
	if *a < b {
		*a = b
		return true
	}
	return false
}
func chmin(a *int, b int) bool {
	if *a > b {
		*a = b
		return true
	}
	return false
}
func cumsumBuild(a []int) []int {
	b := append([]int{0}, a...)
	for i := 1; i < len(b); i++ {
		b[i] += b[i-1]
	}
	return b
}
func bytesAdd(bytes *[]byte, x byte) { *bytes = append(*bytes, x) }
func bytesJoin(a, b []byte) []byte   { return append(a, b...) }
func bytesCopy(a []byte) []byte      { return append([]byte(nil), a...) }

type sortBytes []byte

func (s sortBytes) Less(i, j int) bool  { return s[i] < s[j] }
func (s sortBytes) Swap(i, j int)       { s[i], s[j] = s[j], s[i] }
func (s sortBytes) Len() int            { return len(s) }
func bytesSortAsc(s []byte)             { sort.Sort(sortBytes(s)) }
func bytesSortDesc(s []byte)            { sort.Sort(sort.Reverse(sortBytes(s))) }
func bytesCopySortAsc(s []byte) []byte  { t := bytesCopy(s); bytesSortAsc(t); return t }
func bytesCopySortDesc(s []byte) []byte { t := bytesCopy(s); bytesSortDesc(t); return t }
func bytesReverse(a []byte) {
	for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
		a[i], a[j] = a[j], a[i]
	}
}
func strRepeat(str string, count int) string {
	return strings.Repeat(str, count)
}
func strIsUpperAlphabet(s string) bool {
	if len(s) != 1 {
		panic("wrong arg")
	}
	t := s[0]
	return 'A' <= t && t <= 'Z'
}
func strIsLowerAlphabet(s string) bool {
	if len(s) != 1 {
		panic("wrong arg")
	}
	t := s[0]
	return 'a' <= t && t <= 'z'
}
func strToUpperCase(s string) string { return strings.ToUpper(s) }
func strToLowerCase(s string) string { return strings.ToLower(s) }
func strAlphaUpperCaseToInt(s string) int {
	if len(s) != 1 {
		panic("wrong arg")
	}
	t := s[0]
	if !('A' <= t && t <= 'Z') {
		panic("arg must be upper case alphabet")
	}
	return int(t - 'A')
}
func strAlphaLowerCaseToInt(s string) int {
	if len(s) != 1 {
		panic("wrong arg")
	}
	t := s[0]
	if !('a' <= t && t <= 'z') {
		panic("arg must be lower case alphabet")
	}
	return int(t - 'a')
}
func strCountAlphabetsLower(alphaLower string) (ctAlphas [26]int) {
	ct := [26]int{}
	for _, ss := range alphaLower {
		if !('a' <= ss && ss <= 'z') {
			panic("func strCountAlphabetsLower: argument must be lowercase string")
		}
		ct[ss-'a']++
	}
	return ct
}
func strCountAlphabetsUpper(alphaUpper string) (ctAlphas [26]int) {
	ct := [26]int{}
	for _, ss := range alphaUpper {
		if !('A' <= ss && ss <= 'Z') {
			panic("func strCountAlphabetsUpper: argument must be uppercase string")
		}
		ct[ss-'A']++
	}
	return ct
}
func strReverse(s string) string {
	r := []rune(s)
	for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
		r[i], r[j] = r[j], r[i]
	}
	return string(r)
}
func runeIsUpperAlphabet(r rune) bool { return 'A' <= r && r <= 'Z' }
func runeIsLowerAlphabet(r rune) bool { return 'a' <= r && r <= 'z' }
func runesAdd(runes *[]rune, x rune)  { *runes = append(*runes, x) }
func runesJoin(a, b []rune) []rune    { return append(a, b...) }
func runesCopy(a []rune) []rune       { return append([]rune(nil), a...) }

type sortRunes []rune

func (s sortRunes) Less(i, j int) bool  { return s[i] < s[j] }
func (s sortRunes) Swap(i, j int)       { s[i], s[j] = s[j], s[i] }
func (s sortRunes) Len() int            { return len(s) }
func runesSortAsc(s []rune)             { sort.Sort(sortRunes(s)) }
func runesSortDesc(s []rune)            { sort.Sort(sort.Reverse(sortRunes(s))) }
func runesCopySortAsc(s []rune) []rune  { t := runesCopy(s); runesSortAsc(t); return t }
func runesCopySortDesc(s []rune) []rune { t := runesCopy(s); runesSortDesc(t); return t }
func runesReverse(a []rune) {
	for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
		a[i], a[j] = a[j], a[i]
	}
}
func strToInt(s string) int {
	i, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return i
}
func intToStr(i int) string     { return strconv.Itoa(i) }
func CalcMod(a, mod int) int    { return (a%mod + mod) % mod }
func ModSum(a *int, b, mod int) { *a = (((*a) % mod) + mod + (b % mod)) % mod }
func ModMul(a *int, b, mod int) { *a = (((*a) % mod) * (b % mod)) % mod }
func ModPow(x, y, mod int) int {
	if y < 0 {
		panic("Exponent must be a natural number")
	}
	z := 1
	for ; y != 0; y >>= 1 {
		if y&1 == 1 {
			z = (z * x) % mod
		}
		x = (x * x) % mod
	}
	return z
}
func ModFact(x, mod int) int {
	fact := 1
	for i := 1; i <= x; i++ {
		fact = fact * i % mod
	}
	return fact
}
func ModInv(x, mod int) int { return ModPow(x, mod-2, mod) }
func initMatrixBool(parentSize, childSize int, initialValue bool) *[][]bool {
	res := make([][]bool, parentSize)
	for i := range res {
		res[i] = make([]bool, childSize)
		for j := range res[i] {
			res[i][j] = initialValue
		}
	}
	return &res
}
func initMatrixInt(parentSize, childSize int, initialValue int) *[][]int {
	res := make([][]int, parentSize)
	for i := range res {
		res[i] = make([]int, childSize)
		for j := range res[i] {
			res[i][j] = initialValue
		}
	}
	return &res
}

const (
	scbufsz = 3e6 + 10
	bwbufsz = 1e6
)

var (
	sc = bufio.NewScanner(os.Stdin)
	bw = bufio.NewWriterSize(os.Stdout, bwbufsz)
)

func init() {
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, scbufsz), scbufsz)
}

func ri() int {
	if !sc.Scan() {
		panic("failed to scan")
	}
	if err := sc.Err(); err != nil {
		panic(err)
	}
	b := sc.Bytes()
	g := false
	x := 0
	if b[0] == 45 {
		g = true
		x++
	}
	n := 0
	for i := x; i < len(b); i++ {
		n *= 10
		n += int(b[i] - 48)
	}
	if g {
		n = -n
	}
	return n
}

func ri64() int64 {
	if !sc.Scan() {
		panic("failed to scan")
	}
	if err := sc.Err(); err != nil {
		panic(err)
	}
	b := sc.Bytes()
	g := false
	x := 0
	if b[0] == 45 {
		g = true
		x++
	}
	n := int64(0)
	for i := x; i < len(b); i++ {
		n *= 10
		n += int64(b[i] - 48)
	}
	if g {
		n = -n
	}
	return n
}

func ru() uint {
	if !sc.Scan() {
		panic("failed to scan")
	}
	if err := sc.Err(); err != nil {
		panic(err)
	}
	b := sc.Bytes()
	n := uint(0)
	for i := 0; i < len(b); i++ {
		n *= 10
		n += uint(b[i] - 48)
	}
	return n
}

func ru64() uint64 {
	if !sc.Scan() {
		panic("failed to scan")
	}
	if err := sc.Err(); err != nil {
		panic(err)
	}
	b := sc.Bytes()
	n := uint64(0)
	for i := 0; i < len(b); i++ {
		n *= 10
		n += uint64(b[i] - 48)
	}
	return n
}

func rf() float64 {
	sc.Scan()
	if err := sc.Err(); err != nil {
		panic(err)
	}
	f, err := strconv.ParseFloat(sc.Text(), 64)
	if err != nil {
		panic(err)
	}
	return f
}

func rs() string {
	sc.Scan()
	if err := sc.Err(); err != nil {
		panic(err)
	}
	return sc.Text()
}

func rbs() []byte {
	sc.Scan()
	if err := sc.Err(); err != nil {
		panic(err)
	}
	return sc.Bytes()
}

func rrs() []rune {
	sc.Scan()
	if err := sc.Err(); err != nil {
		panic(err)
	}
	return []rune(sc.Text())
}

func ris(n int) []int {
	s := make([]int, n)
	for i := 0; i < len(s); i++ {
		s[i] = ri()
	}
	return s
}

func risZeroBased(n int) []int {
	s := make([]int, n)
	for i := 0; i < len(s); i++ {
		s[i] = ri() - 1
	}
	return s
}

func ri64s(n int) []int64 {
	s := make([]int64, n)
	for i := 0; i < len(s); i++ {
		s[i] = ri64()
	}
	return s
}

func riis(n int) ([]int, []int) {
	s := make([]int, n)
	t := make([]int, n)
	for i := 0; i < len(s); i++ {
		s[i] = ri()
		t[i] = ri()
	}
	return s, t
}

func ru64s(n int) []uint64 {
	s := make([]uint64, n)
	for i := 0; i < len(s); i++ {
		s[i] = ru64()
	}
	return s
}

func rss(n int) []string {
	s := make([]string, n)
	for i := 0; i < len(s); i++ {
		s[i] = rs()
	}
	return s
}

func pf(format string, a ...interface{}) {
	if _, err := fmt.Fprintf(bw, format, a...); err != nil {
		panic(err)
	}
}

func pln(a ...interface{}) {
	if _, err := fmt.Fprintln(bw, a...); err != nil {
		panic(err)
	}
}

func pF64(x float64) { pf("%.10f\n", x) }

func pints(a []int) {
	for _, v := range a {
		fmt.Fprintln(bw, v)
	}
}

func pintsol(a []int) {
	s := fmt.Sprint(a)
	if _, err := fmt.Fprintln(bw, s[1:len(s)-1]); err != nil {
		panic(err)
	}
}

func dbg(a ...interface{}) {
	if _, err := fmt.Fprintln(os.Stderr, a...); err != nil {
		panic(err)
	}
}

func dbgMatrix(a []interface{}) {
	for i := 0; i < len(a); i++ {
		dbg(a[i])
	}
}

func flush() {
	if err := bw.Flush(); err != nil {
		panic(err)
	}
}

func YESorNO(b bool) string {
	if b {
		return "YES"
	} else {
		return "NO"
	}
}

func YesOrNo(b bool) string {
	if b {
		return "Yes"
	} else {
		return "No"
	}
}

func main() {
	solve()
	flush()
}

const (
	alphabetLower = "abcdefghijklmnopqrstuvwxyz"
	alphabetUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// maxInt64  = 9223372036854775807  // 9e18
	// maxInt32  = 2147483647           // 2e9
	// maxUint64 = 18446744073709551615 // 1e19
	zero   = 0
	i32Inf = 1 << 30
	i64Inf = 1 << 60
	inf    = 1 << 60
	mod    = 1e9 + 7
)

type pair struct{ fi, se int }
type byFiSe []pair

func (p byFiSe) Len() int      { return len(p) }
func (p byFiSe) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p byFiSe) Less(i, j int) bool {
	if p[i].fi == p[j].fi {
		return p[i].se < p[j].se
	}
	return p[i].fi < p[j].fi
}

type point struct{ x, y int }

type IntPair struct{ Fi, Se int }
type SortIntPairByFiSe []IntPair

func (p SortIntPairByFiSe) Len() int      { return len(p) }
func (p SortIntPairByFiSe) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p SortIntPairByFiSe) Less(i, j int) bool {
	if p[i].Fi == p[j].Fi {
		return p[i].Se < p[j].Se
	}
	return p[i].Fi < p[j].Fi
}

func solve() {
	n, k := ri(), ri()
	ps := ris(n)

	idx := 0
	sumMax := 0
	cs := cumsumBuild(ps)
	for i := 0; i+k <= n; i++ {
		sum := cs[i+k] - cs[i]
		if chmax(&sumMax, sum) {
			idx = i
		}
	}

	ans := 0.0
	for i := idx; i < idx+k; i++ {
		ans += floatDiv(sigmaK(ps[i]), ps[i])
	}
	pln(ans)
}


package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
)

// -----------------------------------------------------------------------------

// IO helper functions

// Returns next token from input.  It must be initialized by SetInput()
// before the first call.
var nextToken func() ([]byte, error)
var nextLine func() ([]byte, error)

// Holds a buffer for output.  It must be initialized by SetOutput().
// All IO fucntions (read*() and [e]print*()) should write to OutputWriter
// instead of this.
var OutputBuffer *bufio.Writer

// Holds an io.Writer.  It must be initialized by SetOutput()
var OutputWriter io.Writer

// Set IO functions for interactive input/output.
func SetInteractive(w io.Writer, r io.Reader) {
	SetUnbefferedInput(r)
	OutputBuffer = nil
	OutputWriter = w
}

// Setup OutputBuffer and OutputWriter.
func SetOutput(w io.Writer) {
	OutputBuffer = bufio.NewWriter(w)
	OutputWriter = OutputBuffer
}

// Flushes OutputBuffer
func Flush() {
	if OutputBuffer != nil {
		OutputBuffer.Flush()
	}
}

// Returns true if c is a white space
func IsSpace(c byte) bool {
	switch c {
	case '\t', '\n', '\v', '\f', '\r', ' ':
		return true
	}
	return false
}

func IsNewLine(c byte) bool {
	switch c {
	case '\n', '\r':
		return true
	}
	return false
}

// Setup nextToken with input buffer.
func SetInput(r io.Reader) {
	buf := new(bytes.Buffer)
	var b []byte

	var i int
	rest := func() ([]byte, error) {
		for i < len(b) && IsSpace(b[i]) {
			i++
		}
		if i == len(b) {
			return nil, io.ErrUnexpectedEOF
		}
		j := i
		for i < len(b) && !IsSpace(b[i]) {
			i++
		}
		return b[j:i], nil
	}
	initial := func() ([]byte, error) {
		io.Copy(buf, r)
		b = buf.Bytes()
		nextToken = rest
		return rest()
	}
	nextToken = initial

	restLn := func() ([]byte, error) {
		for i < len(b) && IsNewLine(b[i]) {
			i++
		}
		if i == len(b) {
			return nil, io.ErrUnexpectedEOF
		}
		j := i
		for i < len(b) && !IsNewLine(b[i]) {
			i++
		}
		return b[j:i], nil
	}

	initialLn := func() ([]byte, error) {
		io.Copy(buf, r)
		b = buf.Bytes()
		nextLine = restLn
		return restLn()
	}
	nextLine = initialLn
}

// Setup nextToken without input buffer.
func SetUnbefferedInput(r io.Reader) {
	buf := bufio.NewReader(r)
	var b []byte

	var i int
	nextToken = func() ([]byte, error) {
		var err error
		if i == len(b) {
			b, err = buf.ReadBytes('\n')
			if err != nil {
				return nil, err
			}
			i = 0
			j := len(b) - 1
			for 0 <= j && IsSpace(b[j]) {
				j--
			}
			b = b[0 : j+1]
		}
		for i < len(b) && IsSpace(b[i]) {
			i++
		}
		j := i
		for i < len(b) && !IsSpace(b[i]) {
			i++
		}
		if i == j {
			return nil, io.ErrUnexpectedEOF
		}
		return b[j:i], nil
	}
}

// -----------------------------------------------------------------------------

// IO functions

// Reads next token and return it as []byte
func readb() []byte {
	b, err := nextToken()
	if err != nil {
		panic(err)
	}
	return b
}

// Reads next token and return it as string
func reads() string {
	return string(readb())
}

// Read next line as []byte
func readbln() []byte {
	b, err := nextLine()
	if err != nil {
		panic(err)
	}
	return b
}

// Read next line as string
func readsln() string {
	return string(readbln())
}

// Reads next token and return it as int64
func readll() int64 {
	i, err := strconv.ParseInt(reads(), 10, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// Reads next token and return it as int
func readi() int {
	return int(readll())
}

// Reads next token and return it as float64
func readf() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadIntSlice returns an integer slice that has n integers.
func readislice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// ReadInt64Slice returns as int64 slice that has n integers.
func readllslice(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// Write args to OutputWriter with the format f
func printf(f string, args ...interface{}) (int, error) {
	return fmt.Fprintf(OutputWriter, f, args...)
}

// Write args to OutputWriter without format
func println(args ...interface{}) (int, error) {
	return fmt.Fprintln(OutputWriter, args...)
}

// Write args to stderr with the format f
func eprintf(f string, args ...interface{}) (int, error) {
	return fmt.Fprintf(os.Stderr, f, args...)
}

// Write args to stderr without format
func eprintln(args ...interface{}) (int, error) {
	return fmt.Fprintln(os.Stderr, args...)
}

// -----------------------------------------------------------------------------

// Simple math functions

const (
	// big prime
	INF  = 1000000007
	INF2 = 1000000009
	INF3 = 998244353
)

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func minll(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a < b {
		return b
	}
	return a
}

func maxll(a, b int64) int64 {
	if a < b {
		return b
	}
	return a
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func absll(a int64) int64 {
	if a < 0 {
		return -a
	}
	return a
}

// egcd(a, b) returns d, x, y:
//   d is gcd(a,b)
//   x, y are  integers that satisfy ax + by = d
func egcd(a, b int) (int, int, int) {
	if b == 0 {
		return a, 1, 0
	}
	d, x, y := egcd(b, a%b)
	return d, y, x - a/b*y
}

func egcdll(a, b int64) (int64, int64, int64) {
	if b == 0 {
		return a, 1, 0
	}
	d, x, y := egcdll(b, a%b)
	return d, y, x - a/b*y
}

func gcd(a, b int) int {
	d, _, _ := egcd(a, b)
	return d
}

func gcdll(a, b int64) int64 {
	d, _, _ := egcdll(a, b)
	return d
}

// set up IO functions
func init() {
	// for non-interactive
	SetInput(os.Stdin)
	SetOutput(os.Stdout)

	// Enable below when interactive.  Its ok to leave above intact.
	// SetInteractive(os.Stdout, os.Stdin)
}

func main() {
  defer Flush()

  N,K := readi(), readi()
  P := readislice(N)

  sums := make([]int, 1001)

  for i := 1; i <= 1000; i++{
    sums[i] = sums[i-1] + i
  }

  exps := make([]float64, 1001)

  for i := 1; i <= 1000; i++{
    exps[i] = float64(sums[i]) / float64(i)
  }

  P_exp_sums := make([]float64, N+1)

  for i := 0; i < N; i++{
    P_exp_sums[i+1] = P_exp_sums[i] + exps[P[i]]
  }

  var max float64

  for i, n := range P_exp_sums{
    if i >= K && n - P_exp_sums[i-K] > max{
       max = n - P_exp_sums[i-K]
    }
  }

  println(float64(max))

}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func readInt() int {
	sc.Scan()
	iv, _ := strconv.Atoi(sc.Text())
	return iv
}

func max(x, y float64) float64 {
	if x > y {
		return x
	}
	return y
}

func init() {
	sc.Split(bufio.ScanWords)
}

func main() {
	n, k := readInt(), readInt()
	cs := make([]float64, n+1)
	for i := 1; i <= n; i++ {
		p := readInt()
		cs[i] = (float64(p)+1)/2 + cs[i-1]
	}
	ans := float64(0)
	for i := k; i <= n; i++ {
		ans = max(ans, cs[i]-cs[i-k])
	}
	fmt.Println(ans)
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

var sc = bufio.NewScanner(os.Stdin)

func main() {
	// Code for D - Dice in Line
	var N, K int
	fmt.Scan(&N, &K)

	sc.Split(bufio.ScanWords)
	p := make([]int, N)
	for i := 0; i < N; i++ {
		p[i] = nextInt()
	}

	var max int
	var maxNum int
	var count int
	for i := 0; i < N-K+1; i++ {
		count = 0
		for j := 0; j < K; j++ {
			count += p[i+j]
		}

		if max < count {
			max = count
			maxNum = i
		}
	}

	var ans float64
	for i := 0; i < K; i++ {
		ans += (float64(p[maxNum+i]) + 1.0) / 2.0
	}
	fmt.Println(ans)
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

var sc = bufio.NewScanner(os.Stdin)

func main() {
	// Code for D - Dice in Line
	var N, K int
	fmt.Scan(&N, &K)

	sc.Split(bufio.ScanWords)
	p := make([]int, N)
	for i := 0; i < N; i++ {
		p[i] = nextInt()
	}

	var max float64
	var ans float64
	for i := 0; i < N-K+1; i++ {
		ans = 0
		for j := 0; j < K; j++ {
			ans += (float64(p[i+j]) + 1.0) / 2.0
		}

		if max < ans {
			max = ans
		}
	}
	fmt.Println(max)
}


package main

import (
	"fmt"
	"math"
)

func main() {
	var N, K int
	fmt.Scan(&N, &K)
	p := make([]float64, N)
	for i := range p {
		fmt.Scan(&p[i])
		p[i] = (p[i] + 1) / 2
	}
	wa := make([]float64, N+1)
	for i := 0; i < N; i++ {
		wa[i+1] = wa[i] + p[i]
	}
	max := 0.0
	for i := K; i < N+1; i++ {
		max = math.Max(max, wa[i]-wa[i-K])
	}
	fmt.Println(wa)
	fmt.Println(max)
}


n, k = gets.split.map(&:to_i)
ps = gets.split.map(&:to_i)

max = sum = ps[0...k].inject(:+)

(k...n).each do |i|
  sum = sum - ps[i - k] + ps[i]
  max = sum if max < sum
end

puts (max + k) / 2.0


# frozen_string_literal: true

n, k = gets.split.map &:to_i
p = gets.split.map &:to_i
sum = p[0...k].inject(:+)
temp = sum
(k...n).each do |i|
  temp = temp - p[i-k] + p[i]
  sum = temp if sum < temp
end
puts (sum+k)/2.0


n,k=gets.split.map(&:to_i)
p=gets.split.map(&:to_f)
e=[]
sum=[]
sum[1]=(p[0]+1)/2
ans=sum[1]
(2..n).each do |i|
  e[i]=(p[i-1]+1)/2
  sum[i]=sum[i-1]+e[i]
  ans=[ans,sum[i]-sum[i-k]].max if i-k>0
end
p ans


n,k=gets.split.map(&:to_i)
p=gets.split.map(&:to_f)
e=[]
sum=[]
ans=0
sum[1]=(p[0]+1)/2
(2..n).each do |i|
  e[i]=(p[i-1]+1)/2
  sum[i]=sum[i-1]+e[i]
  ans=[ans,sum[i]-sum[i-k]].max if i-k>0
end
p ans


n,k=gets.split.map(&:to_i)
p=gets.split.map(&:to_i)
sum=[]
sum[k]=p[0,k].sum
a=p[0,k]
max=0

(k+1..n).each do |i|
  sum[i]=sum[i-1]-p[i-k]+p[i-1]
  if max<sum[i]
    a=p[i-k,k]
    max=sum[i]
  end
end

e=0
a.each do |aa|
  (1..aa).each do |i|
    e+=(1/aa.to_f)*i
  end
end
p e


#[macro_use]
mod input_mcr {
    // ref: tanakh <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
    // diff: using Parser
    #[macro_export(local_inner_macros)]
    macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut parser = Parser::from_str($s);
        input_inner!{parser, $($r)*}
    };
    (parser = $parser:ident, $($r:tt)*) => {
        input_inner!{$parser, $($r)*}
    };
    (new_stdin_parser = $parser:ident, $($r:tt)*) => {
        let stdin = std::io::stdin();
        let reader = std::io::BufReader::new(stdin.lock());
        let mut $parser = Parser::new(reader);
        input_inner!{$parser, $($r)*}
    };
    ($($r:tt)*) => {
        input!{new_stdin_parser = parser, $($r)*}
    };
}

    #[macro_export(local_inner_macros)]
    macro_rules! input_inner {
    ($parser:ident) => {};
    ($parser:ident, ) => {};
    ($parser:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($parser, $t);
        input_inner!{$parser $($r)*}
    };
}

    #[macro_export(local_inner_macros)]
    macro_rules! read_value {
    ($parser:ident, ( $($t:tt),* )) => {
        ( $(read_value!($parser, $t)),* )
    };
    ($parser:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($parser, $t)).collect::<Vec<_>>()
    };
    ($parser:ident, chars) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()
    };
    ($parser:ident, char_) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()[0]
    };
    ($parser:ident, usize1) => {
        read_value!($parser, usize) - 1
    };
    ($parser:ident, i64_) => {
        $parser.fast_i64()
    };
    ($parser:ident, usize_) => {
        $parser.fast_i64() as usize
    };
    ($parser:ident, usize1_) => {
        ($parser.fast_i64() - 1) as usize
    };
    ($parser:ident, $t:ty) => {
        $parser.next::<$t>().expect("Parse error")
    };
}

    use std::io;
    use std::io::BufRead;
    use std::str;

    // ref: tatsuya6502 <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e>
    // ref: wariuni <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e#comment-7040a5ae96305e884eb9>
    // diff: using std::io::BufRead::fill_buf()
    pub struct Parser<R> {
        pub reader: R,
        buf: Vec<u8>,
        pos: usize,
    }

    impl Parser<io::Empty> {
        pub fn from_str(s: &str) -> Parser<io::Empty> {
            Parser {
                reader: io::empty(),
                buf: s.as_bytes().to_vec(),
                pos: 0,
            }
        }
    }

    impl<R: BufRead> Parser<R> {
        pub fn new(reader: R) -> Parser<R> {
            Parser {
                reader: reader,
                buf: vec![],
                pos: 0,
            }
        }
        pub fn update_buf(&mut self) {
            self.buf.clear();
            self.pos = 0;
            loop {
                let (len, complete) = {
                    let buf2 = self.reader.fill_buf().unwrap();
                    self.buf.extend_from_slice(buf2);
                    let len = buf2.len();
                    (len, buf2[len - 1] <= 0x20)
                };
                self.reader.consume(len);
                if complete {
                    break;
                }
            }
        }
        pub fn next<T: str::FromStr>(&mut self) -> Result<T, T::Err> {
            loop {
                let mut begin = self.pos;
                while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                    begin += 1;
                }
                let mut end = begin;
                while end < self.buf.len() && (self.buf[end] > 0x20) {
                    end += 1;
                }
                if begin != self.buf.len() {
                    self.pos = end;
                    return unsafe { str::from_utf8_unchecked(&self.buf[begin..end]) }.parse::<T>();
                } else {
                    self.update_buf();
                }
            }
        }
        pub fn fast_i64(&mut self) -> i64 {
            loop {
                let mut begin = self.pos;
                while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                    begin += 1;
                }
                if begin == self.buf.len() {
                    self.update_buf();
                    continue;
                }
                let mut res = 0;
                let (is_positive, mut end) = match self.buf[begin] {
                    b'+' => (true, begin + 1),
                    b'-' => (false, begin + 1),
                    _ => (true, begin),
                };
                while end < self.buf.len() && (self.buf[end] > 0x20) {
                    res = res * 10 + (self.buf[end] as i64 - '0' as i64);
                    end += 1;
                }
                if begin != self.buf.len() {
                    self.pos = end;
                    return if is_positive { res } else { -res };
                } else {
                    self.update_buf();
                }
            }
        }
    }
}

mod cumulative {
    use std::ops::*;

    pub fn cu<T: Add<Output = T> + Copy>(zero: T, xs: &Vec<T>) -> Vec<T> {
        let mut res = vec![zero; xs.len() + 1];
        for (i, &x) in xs.iter().enumerate() {
            res[i + 1] = res[i] + x;
        }
        res
    }
}

use input_mcr::*;
use std::cmp::*;

use cumulative::*;

fn main() {
    input! {
        n: usize,
        m: usize,
        xs: [i64; n],
    }
    let xs_cu = cu(0, &xs);
    let mut res = 0;
    for i in 0..n - m + 1 {
        let t = xs_cu[i + m] - xs_cu[i] + m as i64;
        res = max(res, t);
    }
    println!("{}", res as f64 / 2.0);
}