Problem:
Score : 1700 points

Problem Statement

There is a railroad in Takahashi Kingdom.
The railroad consists of N sections, numbered 1, 2, ..., N, and N+1 stations, numbered 0, 1, ..., N. Section i directly connects the stations i-1 and i.
A train takes exactly A_i minutes to run through section i, regardless of direction.
Each of the N sections is either single-tracked over the whole length, or double-tracked over the whole length.
If B_i = 1, section i is single-tracked; if B_i = 2, section i is double-tracked.
Two trains running in opposite directions can cross each other on a double-tracked section, but not on a single-tracked section.
Trains can also cross each other at a station.

Snuke is creating the timetable for this railroad. In this timetable, the trains on the railroad run every K minutes, as shown in the following figure. Here, bold lines represent the positions of trains running on the railroad. (See Sample 1 for clarification.)

When creating such a timetable, find the minimum sum of the amount of time required for a train to depart station 0 and reach station N, and the amount of time required for a train to depart station N and reach station 0.
It can be proved that, if there exists a timetable satisfying the conditions in this problem, this minimum sum is always an integer.

Formally, the times at which trains arrive and depart must satisfy the following:

Each train either departs station 0 and is bound for station N, or departs station N and is bound for station 0.

Each train takes exactly A_i minutes to run through section i. For example, if a train bound for station N departs station i-1 at time t, the train arrives at station i exactly at time t+A_i.

Assume that a train bound for station N arrives at a station at time s, and departs the station at time t. Then, the next train bound for station N arrives at the station at time s+K, and departs the station at time t+K. Additionally, the previous train bound for station N arrives at the station at time s-K, and departs the station at time t-K. This must also be true for trains bound for station 0.

Trains running in opposite directions must not be running on the same single-tracked section (except the stations at both ends) at the same time.

Constraints

1 \leq N \leq 100000

1 \leq K \leq 10^9

1 \leq A_i \leq 10^9

A_i is an integer.

B_i is either 1 or 2.

Partial Score

In the test set worth 500 points, all the sections are single-tracked. That is, B_i = 1.

In the test set worth another 500 points, N \leq 200.

Input

The input is given from Standard Input in the following format:

N K
A_1 B_1
A_2 B_2
:
A_N B_N

Output

Print an integer representing the minimum sum of the amount of time required for a train to depart station 0 and reach station N, and the amount of time required for a train to depart station N and reach station 0.
If it is impossible to create a timetable satisfying the conditions, print -1 instead.

Sample Input 1

3 10
4 1
3 1
4 1

Sample Output 1

26

For example, the sum of the amount of time in question will be 26 minutes in the following timetable:

In this timetable, the train represented by the red line departs station 0 at time 0, arrives at station 1 at time 4, departs station 1 at time 5, arrives at station 2 at time 8, and so on.

Sample Input 2

1 10
10 1

Sample Output 2

-1

Sample Input 3

6 4
1 1
1 1
1 1
1 1
1 1
1 1

Sample Output 3

12

Sample Input 4

20 987654321
129662684 2
162021979 1
458437539 1
319670097 2
202863355 1
112218745 1
348732033 1
323036578 1
382398703 1
55854389 1
283445191 1
151300613 1
693338042 2
191178308 2
386707193 1
204580036 1
335134457 1
122253639 1
824646518 2
902554792 2

Sample Output 4

14829091348

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

using System;
using System.Text;
using System.Collections.Generic;
class Solve{
    public Solve(){}
    StringBuilder sb;
    public static int Main(){
        new Solve().Run();
        return 0;
    }
    void Run(){
        sb = new StringBuilder();
        Calc();
        Console.Write(sb.ToString());
    }
    void Calc(){
        string[] str = Console.ReadLine().Split(' ');
        int N = int.Parse(str[0]);
        long K = int.Parse(str[1]);
        long[] L = new long[N];
        long[] R = new long[N];
        int eN = 0;
        long sum = 0;
        {
            for(int i=0;i<N;i++){
                str = Console.ReadLine().Split(' ');
                long D = int.Parse(str[0]);
                bool b = int.Parse(str[1]) == 1;
                if(b && 2*D > K){
                    sb.Append("-1\n");
                    return;
                }
                if(b){
                    L[eN] = K - (((sum + 2*D) % K) == 0 ? K : ((sum + 2*D) % K));
                    R[eN] = K - ((sum % K) == 0 ? K : sum % K);
                    eN++;
                }
                sum += 2*D;
            }
        }
        long[] DPL = new long[eN];
        long[] DPR = new long[eN];
        long[] Points = new long[2*eN];
        int[] A = new int[2*eN];
        for(int i=0;i<eN;i++){
            Points[2*i] = L[i];
            Points[2*i+1] = R[i];
            A[2*i] = 2*i;
            A[2*i+1] = 2*i+1;
        }
        Array.Sort(Points,A);
        int[] B = new int[2*eN];
        for(int i=0;i<2*eN;i++){
            B[A[i]] = i;
        }
        SegTree Seg = new SegTree(2*eN,this);
        for(int i=4*eN-2;i>=0;i--){
            Seg.X[i] = eN;
        }
        for(int i=eN-1;i>=0;i--){
            int lp = B[2*i];
            int rp = B[2*i+1];
            int gL = Seg.Get(lp);
            DPL[i] = gL == eN ? 0 : DPR[gL] + (K + Points[B[2*gL+1]] - Points[lp]) % K;
            int gR = Seg.Get(rp);
            DPR[i] = gR == eN ? 0 : DPR[gR] + (K + Points[B[2*gR+1]] - Points[rp]) % K;
            int bf = 0;
            int bl = 2*eN;
            long C = Points[B[2*i]];
            while(bf != bl){
                int bc = (bf+bl)/2;
                if(bc == 2*eN || C < Points[bc]){
                    bl = bc;
                }
                else{
                    bf = bc+1;
                }
            }
            int l = bf;
            bf = -1;
            bl = 2*eN-1;
            C = Points[B[2*i+1]];
            while(bf != bl){
                int bc = (bf+bl+1)/2;
                if(bc == -1 || C > Points[bc]){
                    bf = bc;
                }
                else{
                    bl = bc-1;
                }
            }
            int r = bf;
            if(Points[lp] < Points[rp]){
                if(l <= r){
                    Seg.Add(i,l,r);
                }
            }
            else{
                if(l != 2*eN){
                    Seg.Add(i,l,2*eN-1);
                }
                if(r != -1){
                    Seg.Add(i,0,r);
                }
            }
        }
        for(int i=4*eN-2;i>=0;i--){
            Seg.X[i] = eN;
        }
        long min = DPR[0];
        for(int i=0;i<eN;i++){
            int lp = B[2*i];
            int rp = B[2*i+1];
            int gL = Seg.Get(lp);
            if(gL == eN){
                min = Math.Min(min,DPL[i]);
            }
            int gR = Seg.Get(rp);
            if(gR == eN){
                min = Math.Min(min,DPR[i]);
            }
            int bf = 0;
            int bl = 2*eN;
            long C = Points[B[2*i]];
            while(bf != bl){
                int bc = (bf+bl)/2;
                if(bc == 2*eN || C < Points[bc]){
                    bl = bc;
                }
                else{
                    bf = bc+1;
                }
            }
            int l = bf;
            bf = -1;
            bl = 2*eN-1;
            C = Points[B[2*i+1]];
            while(bf != bl){
                int bc = (bf+bl+1)/2;
                if(bc == -1 || C > Points[bc]){
                    bf = bc;
                }
                else{
                    bl = bc-1;
                }
            }
            int r = bf;
            if(Points[lp] < Points[rp]){
                if(l <= r){
                    Seg.Add(0,l,r);
                }
            } 
            else{
                if(l != 2*eN){
                    Seg.Add(0,l,2*eN-1);
                }
                if(r != -1){
                    Seg.Add(0,0,r);
                }
            }
        }
        sb.Append((min+sum)+"\n");
    }
}
struct SegTree{
    Solve Sol;
    public int[] X;
    //葉の最初の場所
    public int segf;
    //segfのbit
    public int segfb;
    //葉の深さの内浅い方
    public int depth;
    //浅い葉の内座標が最大のもの
    public int borderP;
    //はみ出すものの数
    public int border;
    public SegTree(int N,Solve So){
        Sol = So;
        X = new int[2*N-1];
        for(depth = 1;(1 << depth) <= N;depth++){
            ;
        }
        segf = N-1;
        borderP = (1 << depth) - 2;
        border = 2*N - borderP - 2;
        segfb = border/2;
    }
    public int ToBit(int p){
        if(p >= border){
            return segfb + p - border;
        }
        else{
            return p;
        }
    }
    //葉のある場所
    public int ToLeaf(int p){
        if(p >= border){
            return segf + p - border;
        }
        else{
            return borderP + p + 1;
        }
    }
    //葉の示す頂点
    public int ToPoint(int leaf){
        if(leaf > borderP){
            return leaf - borderP - 1;
        }
        else{
            return leaf - segf + border;
        }
    }
    public int Get(int p){
        //葉の作業
        int min = X[ToLeaf(p)];
        //親の作業
        for(int v=ToLeaf(p);v!=0;v=(v-1)/2){
            int spa = (v-1)/2;
            int sl = (v-1)/2*2+1;
            int sr = (v-1)/2*2+2;
            min = Math.Min(min,X[spa]);
        }
        return min;
    }
    //vの子の内bより大きいものに(bは子孫,bはToBitしたもの)
    void More(int C,int b,int v,int depth){
        if((b & (1 << depth)) == 0){
            //右の子は全てbより大きい
            if(((b+1) % (1 << depth)) != 0){
                More(C,b,v*2+1,depth-1);
                Act(C,v*2+2);
            }
            else{
                Act(C,v*2+2);
            }
        }
        else{
            //左の子は全てb未満
            More(C,b,v*2+2,depth-1);
        }
    }
    //vの子の内bより小さなものに(bは子孫,bはToBitしたもの)
    void Less(int C,int b,int v,int depth){
        if((b & (1 << depth)) == 0){
            //右の子は全てbより大きい
            Less(C,b,v*2+1,depth-1);
        }
        else{
            //左の子は全てb未満
            if(b % (1 << depth) != 0){
                Act(C,v*2+1);
                Less(C,b,v*2+2,depth-1);
            }
            else{
                //右の子は全てb以上
                Act(C,v*2+1);
            }
        }
    }
    void Section(int C,int bl,int br,int v,int dl,int dr){
        if(v >= segf){
            //葉
            Act(C,v);
        }
        else{
            if((bl & (1 << dl)) == 0 && (br & (1 << dr)) == 0){
                //両方左
                Section(C,bl,br,v*2+1,dl-1,dr-1);
            }
            else if((bl & (1 << dl)) != 0 && (br & (1 << dr)) != 0){
                //両方右
                Section(C,bl,br,v*2+2,dl-1,dr-1);
            }
            else{
                //左と右に分かれた
                if(bl % (1 << dl) != 0){
                    More(C,bl-1,v*2+1,dl-1);
                }
                else{
                    //左は全て含まれる
                    Act(C,v*2+1);
                }
                if((br + 1) % (1 << dl) != 0){
                    Less(C,br+1,v*2+2,dr-1);
                }
                else{
                    //右は全て含まれる
                    Act(C,v*2+2);
                }
            }
        }
    }
    public void Add(int C,int l0,int r0){
        int bl = ToBit(l0);
        int br = ToBit(r0);
        int dl = l0 >= border ? depth - 2 : depth - 1;
        int dr = r0 >= border ? depth - 2 : depth - 1;
        Section(C,bl,br,0,dl,dr);
    }
    void Act(int C,int v){
        X[v] = C;
    }
}