Problem:
Problem D:
So Sleepy
You have an appointment to meet a friend of yours today, but you are so sleepy because you
didn’t sleep well last night.
As you will go by trains to the station for the rendezvous, you can have a sleep on a train. You
can start to sleep as soon as you get on a train and keep asleep just until you get off. However,
because of your habitude, you can sleep only on one train on your way to the destination.
Given the time schedule of trains as well as your departure time and your appointed time, your
task is to write a program which outputs the longest possible time duration of your sleep in a
train, under the condition that you can reach the destination by the appointed time.
Input
The input consists of multiple datasets. Each dataset looks like below:
S T
D Time
D
A Time
A
N
1
K
1,1
Time
1,1
...
K
1,
N
1
Time
1,
N
1
N
2
K
2,1
Time
2,1
...
K
2,
N
2
Time
2,
N
2
...
N
T
K
T
,1
Time
T
,1
...
K
T
,
N
T
Time
T
,
N
T
The first line of each dataset contains S (1 ≤ S ≤ 1000) and
T
(0 ≤
T
≤ 100), which denote
the numbers of stations and trains respectively. The second line contains the departure station
(
D
), the departure time (
Time
D
), the appointed station (
A
), and the appointed time (
Time
A
), in this order. Then
T
sets of time schedule for trains follow. On the first line of the
i
-th set,
there will be
N
i
which indicates the number of stations the
i
-th train stops at. Then
N
i
lines
follow, each of which contains the station identifier (
K
i,j
) followed by the time when the train
stops at (i.e. arrives at and/or departs from) that station (
Time
i,j
).
Each station has a unique identifier, which is an integer between 1 and
S
. Each time is given
in the format
hh
:
mm
, where
hh
represents the two-digit hour ranging from “00” to “23”, and
mm
represents the two-digit minute from “00” to “59”.
The input is terminated by a line that contains two zeros.
You may assume the following:
each train stops at two stations or more;
each train never stops at the same station more than once;
a train takes at least one minute from one station to the next;
all the times that appear in each dataset are those of the same day; and
as being an expert in transfer, you can catch other trains that depart at the time just you
      arrive the station.
Output
For each dataset, your program must output the maximum time in minutes you can sleep if you
can reach to the destination station in time, or “impossible” (without the quotes) otherwise.
Sample Input
3 1
1 09:00 3 10:00
3
1 09:10
2 09:30
3 09:40
3 2
1 09:00 1 10:00
3
1 09:10
2 09:30
3 09:40
3
3 09:20
2 09:30
1 10:00
1 0
1 09:00 1 10:00
1 0
1 10:00 1 09:00
3 1
1 09:00 3 09:35
3
1 09:10
2 09:30
3 09:40
4 3
1 09:00 4 11:00
3
1 09:10
2 09:20
4 09:40
3
1 10:30
3 10:40
4 10:50
4
1 08:50
2 09:30
3 10:30
4 11:10
0 0
Output for the Sample Input
30
30
0
impossible
impossible
60

Submitted solutions:

code_snippet: #include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

int dp[1000][24 * 60][2];
int n, m, dest, destTime;

vector<pair<int, int>> lines[100], stationInfo[1000][24 * 60]; // time, station / line index

int getAns(int station, int time, bool slept) {
	if(time > destTime) return -2;

	int &ret = dp[station][time][slept];
	if(ret != -1) return ret;

	ret = -2;
	if(station == dest) ret = 0;
	ret = max(ret, getAns(station, time + 1, slept));
	for(auto &info: stationInfo[station][time]) {
		int nextLine = info.first;
		int stIndex = info.second;
		if(stIndex + 1 < lines[nextLine].size())
			ret = max(ret, getAns(lines[nextLine][stIndex + 1].second, lines[nextLine][stIndex + 1].first, slept));
		if(!slept)
			for(int ind = stIndex + 1; ind < lines[nextLine].size(); ind++) {
				int res = getAns(lines[nextLine][ind].second, lines[nextLine][ind].first, true);
				if(res >= 0)
					ret = max(ret, res + lines[nextLine][ind].first - lines[nextLine][stIndex].first);
			}
	}

	return ret;
}

int main(void) {
	while(scanf("%d %d", &n, &m), n > 0) {
		for(int i = 0; i < m; i++) lines[i].clear();
		for(int i = 0; i < n; i++)
			for(int j = 0; j < 24 * 60; j++)
				stationInfo[i][j].clear();

		int start, startTime, temp[2];
		scanf("%d %d:%d", &start, temp, temp + 1);
		startTime = temp[0] * 60 + temp[1];
		scanf("%d %d:%d", &dest, temp, temp + 1);
		destTime = temp[0] * 60 + temp[1];
		start--, dest--;

		for(int i = 0; i < m; i++) {
			int visitn;
			scanf("%d", &visitn);
			for(int j = 0; j < visitn; j++) {
				int station;
				scanf("%d %d:%d", &station, temp, temp + 1);
				lines[i].push_back(make_pair(temp[0] * 60 + temp[1], station - 1));
				stationInfo[station - 1][temp[0] * 60 + temp[1]].push_back(make_pair(i, j));
			}
		}

		memset(dp, -1, sizeof(dp));
		int res = getAns(start, startTime, false);
		if(res == -2) printf("impossible\n");
		else printf("%d\n", res);
	}

	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 55888
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 1440

struct Info{
	Info(int arg_station_id,int arg_stop_time){
		station_id = arg_station_id;
		stop_time = arg_stop_time;
	}
	bool operator<(const struct Info &arg) const{
		return stop_time < arg.stop_time;
	}
	int station_id,stop_time;
};

struct Data{
	Data(int arg_train_id,int arg_stop_index){
		train_id = arg_train_id;
		stop_index = arg_stop_index;
	}
	int train_id,stop_index;
};

int start,start_time;
int goal,goal_time;
int num_station,num_train;
int dp[1005][NUM];
vector<Info> TRAIN[105];
vector<Data> STATION[1005][NUM];

int getTime(char buf[6]){

	int hour = 10*(buf[0]-'0')+(buf[1]-'0');
	int minute = 10*(buf[3]-'0')+(buf[4]-'0');

	return 60*hour+minute;
}

void func(){

	for(int i = 0; i < num_station; i++){
		for(int k = 0; k < NUM; k++){

			STATION[i][k].clear();
		}
	}

	for(int i = 0; i < num_train; i++){

		TRAIN[i].clear();
	}

	char buf[6];

	scanf("%d %s",&start,buf);
	start--;
	start_time = getTime(buf);

	scanf("%d %s",&goal,buf);
	goal--;
	goal_time = getTime(buf);

	int num_stop;
	int station_id,stop_time;

	for(int i = 0; i < num_train; i++){

		scanf("%d",&num_stop);

		for(int k = 0; k < num_stop; k++){

			scanf("%d %s",&station_id,buf);
			station_id--;
			stop_time = getTime(buf);

			TRAIN[i].push_back(Info(station_id,stop_time));
		}
		sort(TRAIN[i].begin(),TRAIN[i].end());
	}

	if(start_time > goal_time){

		printf("impossible\n");
		return;
	}

	for(int i = 0; i < num_train; i++){
		for(int k = 0; k < TRAIN[i].size(); k++){

			STATION[TRAIN[i][k].station_id][TRAIN[i][k].stop_time].push_back(Data(i,k));
		}
	}

	for(int i = 0; i < num_station; i++){
		for(int k = start_time; k <= goal_time; k++){

			dp[i][k] = -1;
		}
	}

	dp[start][start_time] = 0;

	int train_id,stop_index;

	for(int k = start_time; k < goal_time; k++){
		for(int i = 0; i < num_station; i++){

			if(dp[i][k] == -1)continue;
			dp[i][k+1] = max(dp[i][k+1],dp[i][k]);

			for(int a = 0; a < STATION[i][k].size(); a++){

				train_id = STATION[i][k][a].train_id;
				stop_index = STATION[i][k][a].stop_index;

				for(int b = stop_index+1; b < TRAIN[train_id].size(); b++){

					if(TRAIN[train_id][b].stop_time > goal_time)break;

					station_id = TRAIN[train_id][b].station_id;
					stop_time = TRAIN[train_id][b].stop_time;

					dp[station_id][stop_time] = max(dp[station_id][stop_time],max(dp[i][k],stop_time-k));
				}
			}
		}
	}

	int ans = -1;

	for(int i = start_time; i <= goal_time; i++){

		ans = max(ans,dp[goal][i]);
	}

	if(ans == -1){

		printf("impossible\n");

	}else{

		printf("%d\n",ans);
	}
}

int main(){

	while(true){

		scanf("%d %d",&num_station,&num_train);
		if(num_station == 0 && num_train == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 50052
final_rank: 6

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

int N,M,S,T;
int st, ed;

unordered_map<int,vector<int>> R;
unordered_map<int,vector<int>> tr;

int ghs(int a,int b){
  return a * 24*60 + b;
}

int gettime(int t1,int t2){
  return t1*60 + t2;
}

const int INF = (1<<29);
typedef pair<int,int> P;
P dp[60*24+1][1101];
void update(P &a, P b){
  if( a.first < b.first ) a.first = b.first;
  if( a.second < b.second ) a.second = b.second;
  if( a.first < a.second ) a.first = a.second;
}
int solve(){
  fill( dp[0], dp[ed+1], P(-INF,-INF) );
  dp[st][S+M] = P(0,0);  
  for(int t=st;t<=ed;t++){
    for(int i=0;i<N+M;i++){
      int id = i%(N+M);
      if( dp[t][id].first == -INF ) continue;    
      if( id < M ) { // train
        if( R.count( ghs(id,t) ) )
          for( int nid : R[ghs(id,t)] )
            update( dp[t][nid+M], P(dp[t][id].first,0) );
        update( dp[t+1][id], P(dp[t][id].first,dp[t][id].second+1) );
      } else { //station
        int x = id-M;
        if( tr.count( ghs(x,t) ) )
          for( int nid : tr[ghs(x,t)] )
            update( dp[t+1][nid], P(dp[t][id].first,1) );
        update( dp[t+1][id], P(dp[t][id].first,0) );        
      }
    }
  }
  return dp[ed][T+M].first;
}


int main(){
  while( ~scanf("%d%d",&N,&M) && (N|M) ) {
    int t1,t2,t3,t4;
    scanf("%d %d:%d %d %d:%d",&S, &t1, &t2, &T, &t3, &t4);
    --S; --T;
    st = gettime( t1, t2 ), ed = gettime( t3, t4 );
    
    for(int i=0;i<M;i++){
      int n; scanf("%d",&n);      
      for(int j=0;j<n;j++){
        int k;
        scanf("%d %d:%d",&k,&t1,&t2);
        --k;        
        R[ghs(i,gettime(t1,t2))].emplace_back(k);
        tr[ghs(k,gettime(t1,t2))].emplace_back(i);
        //cout << i << " "<< gettime(t1,t2) << " " << R[i][gettime(t1,t2)] << endl;
        // cout << k << " "<< gettime(t1,t2) << " " << tr[k][gettime(t1,t2)] << endl;
      }            
    }

    int res = solve();
    if( res < 0 ) printf("impossible\n");
    else printf("%d\n",res);
    tr.clear();
    R.clear();
  }
}
accuracy: 1
time_ms: 470
memory_kb: 30312
final_rank: 4

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

const char EMPTY = 'X';
 
struct Node{
  short value;
  char lazy;
  short lazy_coef; 
  Node(short value=0,char lazy=EMPTY,short lazy_coef=0):value(value),lazy(lazy),lazy_coef(lazy_coef){}
};
 
class SegTree{
public:
  vector<Node> RMQ;
  int limit,N; // N は要素数
 
  void init(int tmp){
    N = tmp;
    int N_N = 1;
    while(N_N < N)N_N *= 2;
    limit = N_N;
    RMQ.clear();
    RMQ.resize(2.3*limit);
    rep(i,2.3*limit-1) RMQ[i] = Node();
  }

  short _build(int cur,int L,int R){
    if( !( 0 <= cur && cur < 2*limit-1 ) ) return 0;
    if( L == R-1 ){
      if( L >= N ) return 0;
      RMQ[cur] = 0; // RMQ の各要素を０で初期化、 1 なら RMQ[cur] = 1などなど...
    } else {
      short vl = _build(cur*2+1,L,(L+R)/2);
      short vr = _build(cur*2+2,(L+R)/2,R);
      RMQ[cur].value = vl+vr;
    }
    return RMQ[cur].value;
  }

  void build() { _build(0,0,limit); }

  inline void value_evaluate(int index,int L,int R){
    if( RMQ[index].lazy == 'A' ){
      RMQ[index].value += ( R - L ) * RMQ[index].lazy_coef;
    } else if( RMQ[index].lazy == 'S' ){
      RMQ[index].value = ( R - L ) * RMQ[index].lazy_coef;
    }
  }
   
  inline void lazy_evaluate(int index,int L,int R){
    value_evaluate(index,L,R);
    if( index < limit && RMQ[index].lazy != EMPTY ) {
      if( RMQ[index].lazy == 'A' ) {
        if( RMQ[index*2+1].lazy == EMPTY ) RMQ[index*2+1].lazy = 'A'; 
        if( RMQ[index*2+2].lazy == EMPTY ) RMQ[index*2+2].lazy = 'A';
        RMQ[index*2+1].lazy_coef += RMQ[index].lazy_coef;
        RMQ[index*2+2].lazy_coef += RMQ[index].lazy_coef;
      } else if( RMQ[index].lazy == 'S') {
        RMQ[index*2+1].lazy = RMQ[index*2+2].lazy = 'S';
        RMQ[index*2+1].lazy_coef = RMQ[index].lazy_coef;
        RMQ[index*2+2].lazy_coef = RMQ[index].lazy_coef;
      }
    }
    RMQ[index].lazy = EMPTY;
    RMQ[index].lazy_coef = 0;
  }
 
  inline void value_update(int index){ RMQ[index].value = RMQ[index*2+1].value + RMQ[index*2+2].value; }

  void _update(int a,int b,char opr,int v,int index,int L,int R){
    lazy_evaluate(index,L,R);
    if( b <= L || R <= a )return;
    if( a <= L && R <= b ){
      RMQ[index].lazy = opr; // 今いるノードに遅延を設定して処理をしてもらう
      if( opr == 'A' )      RMQ[index].lazy_coef += v; 
      else if( opr == 'S' ) RMQ[index].lazy_coef = v; 
      lazy_evaluate(index,L,R);
      return;
    }
    _update(a,b,opr,v,index*2+1,L,(L+R)/2);
    _update(a,b,opr,v,index*2+2,(L+R)/2,R);
    value_update(index);
  }

  void update(int a,int b,char opr,short v){ _update(a,b,opr,v,0,0,limit); } 

  int _query(int a,int b,int index,int L,int R){
    lazy_evaluate(index,L,R); 
    if( b <= L || R <= a ) return 0;
    if( a <= L && R <= b ) return RMQ[index].value;
    short tmp1 = _query(a,b,index*2+1,L,(L+R)/2);
    short tmp2 = _query(a,b,index*2+2,(L+R)/2,R);
    short ret = tmp1+tmp2;
    value_update(index); //ここまでくると子の値が正しくなっているのでその和をとって今いるノードにも正しい値をいれる
    return ret;
  }
  short query(int a,int b) { return _query(a,b,0,0,limit); }
};

typedef pair<int,int> ii;
const int MAX_V = 1001;
struct Edge {
  int src,dst,depart,arrive;
};

int S,T,D,timeD,Rendezvous,timeRendezvous;

inline int toMinute(string s) { 
  int ret = ( s[3] - '0' ) * 10 + ( s[4] - '0' );
  return ret + ( ( s[0] - '0' ) * 10 + ( s[1] - '0' ) ) * 60;
}

struct Data {
  int cur,time;
  bool operator < ( const Data &data ) const { 
    if( time != data.time ) return time > data.time;
    return cur > data.cur;
  }
};

const int MAX_T = 1441;
vector<Edge> G[MAX_V],rG[MAX_V];
SegTree dp[MAX_V][2]; // dp[station][ 0 : from dept, 1 : to rendezvous] := reachable?
vector<vector<bool> > used;

void compute(vector<int> &N,vector<vector<ii> > &KT){
  rep(i,S) rep(j,2) {
    dp[i][j].init(MAX_T);
    dp[i][j].build();
  }
  
  // dept to other station
  used.clear();
  used.resize(S,vector<bool>(MAX_T,false));
  dp[D][0].update(timeD,MAX_T,'S',1);
  used[D][timeD] = true;
  priority_queue<Data> Q;
  Q.push((Data){D,timeD});
  while( !Q.empty() ){
    Data data = Q.top(); Q.pop();
    rep(i,(int)G[data.cur].size()){
      if( data.time > G[data.cur][i].depart ) continue;
      int next = G[data.cur][i].dst;
      int arrive = G[data.cur][i].arrive;
      if( !used[next][arrive] ) {
        used[next][arrive] = true;
        dp[next][0].update(arrive,1500,'S',1);
        Q.push((Data){next,arrive});
      }
    }
  }

  // each station to ランデヴー
  rep(i,used.size()) rep(j,used[i].size()) used[i][j] = false;
  dp[Rendezvous][1].update(0,timeRendezvous+1,'S',1);
  used[Rendezvous][timeRendezvous] = true;
  assert( Q.empty() );
  Q.push((Data){Rendezvous,timeRendezvous});
  while( !Q.empty() ){
    Data data = Q.top(); Q.pop();
    rep(i,(int)rG[data.cur].size()){
      if( data.time < rG[data.cur][i].depart ) continue;
      int prev = rG[data.cur][i].dst;
      int r_arrive = rG[data.cur][i].arrive;
      if( !used[prev][r_arrive] ){
        used[prev][r_arrive] = true;
        dp[prev][1].update(0,r_arrive+1,'S',1);
        Q.push((Data){prev,r_arrive});
      }
    }
  }
  int maxi = -1;
  rep(i,N.size()){
    rep(j,N[i]-1) {
      int f = KT[i][j].first, ft = KT[i][j].second;
      if( !dp[f][0].query(ft,ft+1) ) continue;
      REP(k,j+1,N[i]){
        int t = KT[i][k].first, tt = KT[i][k].second;
        int sleep = tt - ft;
        assert( sleep >= 1 );
        if( sleep <= maxi ) continue;
        if( dp[t][1].query(tt,tt+1) ) {
          maxi = max(maxi,sleep);
        }
      }
    }
  }
  
  if( maxi == -1 && D == Rendezvous && timeD <= timeRendezvous ) puts("0");
  else if( maxi == -1 ) puts("impossible");
  else printf("%d\n",maxi);
}


int main(){
  while( scanf("%d %d",&S,&T), S|T ){
    rep(i,S) G[i].clear(), rG[i].clear();
    rep(i,MAX_V) rep(j,2) dp[i][j].RMQ.clear();
    string temp;
    cin >> D >> temp;
    --D;
    timeD = toMinute(temp);
    cin >> Rendezvous >> temp;
    --Rendezvous;
    timeRendezvous = toMinute(temp);
    vector<int> N(T);
    vector<vector<ii> > KT(T,vector<ii>());
    rep(i,T){
      cin >> N[i];
      KT[i].resize(N[i]);
      rep(j,N[i]) {
        cin >> KT[i][j].first >> temp;
        --KT[i][j].first;
        KT[i][j].second = toMinute(temp);
      }
      rep(j,N[i]-1) {
        int f = KT[i][j].first  , ft = KT[i][j].second;
        int t = KT[i][j+1].first, tt = KT[i][j+1].second;
         G[f].push_back((Edge){f,t,ft,tt});
        rG[t].push_back((Edge){t,f,tt,ft});
      }
    }

    compute(N,KT);
    
  }
  return 0;
}
accuracy: 1
time_ms: 2270
memory_kb: 62088
final_rank: 9

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

const char EMPTY = 'X';
 
struct Node{
  short value;
  /*
    lazy : 
    A : 加算の遅延 ( ADD )
    S : 区間の要素を指定した値にする遅延 ( SET )

    lazy_coef : 
    区間にいくら加算するのかor何をセットするのかを記録
   */
  char lazy;
  short lazy_coef; 
  Node(short value=0,char lazy=EMPTY,short lazy_coef=0):value(value),lazy(lazy),lazy_coef(lazy_coef){}
};
 
class SegTree{
public:
  vector<Node> RMQ;
  int limit,N; // N は要素数
 
  void init(int tmp){
    N = tmp;
    int N_N = 1;
    while(N_N < N)N_N *= 2;
    limit = N_N;
    RMQ.clear();
    RMQ.resize(2.3*limit);
    rep(i,2.3*limit-1) RMQ[i] = Node();
  }

  /* 
  O(n)でRMQを初期化
  [L,R)
  tuple<int,int,int>(総和、最小値、最大値)
  */
  short _build(int cur,int L,int R){
    if( !( 0 <= cur && cur < 2*limit-1 ) ) return 0;
    if( L == R-1 ){
      if( L >= N ) return 0;
      //各要素の値が一定でない場合 ( 配列に初期値をいれてそれで初期化する場合 )
      //buf[] を用意し値を入れ RMQ[cur].value = buf[L]; とする
      // RMQのL番目の要素をbuf[L]で更新
      //RMQ[cur].value = buf[L];

      //各要素が全て同じの場合
      RMQ[cur] = 0; // RMQ の各要素を０で初期化、 1 なら RMQ[cur] = 1などなど...
      //minimum_dat[cur] = 0;
      //maximum_dat[cur] = 0;
    } else {
      short vl = _build(cur*2+1,L,(L+R)/2);
      short vr = _build(cur*2+2,(L+R)/2,R);
      RMQ[cur].value = vl+vr;
    }
    return RMQ[cur].value;
  }

  //initしてから使用すること!!! でないとlimitに正しい値が入っていません
  void build() { _build(0,0,limit); }

  inline void value_evaluate(int index,int L,int R){
    if( RMQ[index].lazy == 'A' ){
      RMQ[index].value += ( R - L ) * RMQ[index].lazy_coef;
    } else if( RMQ[index].lazy == 'S' ){
      RMQ[index].value = ( R - L ) * RMQ[index].lazy_coef;
    }
  }
   
  inline void lazy_evaluate(int index,int L,int R){
    value_evaluate(index,L,R);
    if( index < limit && RMQ[index].lazy != EMPTY ) {
      if( RMQ[index].lazy == 'A' ) {
        if( RMQ[index*2+1].lazy == EMPTY ) RMQ[index*2+1].lazy = 'A'; 
        if( RMQ[index*2+2].lazy == EMPTY ) RMQ[index*2+2].lazy = 'A';
        RMQ[index*2+1].lazy_coef += RMQ[index].lazy_coef;
        RMQ[index*2+2].lazy_coef += RMQ[index].lazy_coef;
      } else if( RMQ[index].lazy == 'S') {
        RMQ[index*2+1].lazy = RMQ[index*2+2].lazy = 'S';
        RMQ[index*2+1].lazy_coef = RMQ[index].lazy_coef;
        RMQ[index*2+2].lazy_coef = RMQ[index].lazy_coef;
      }
    }
    RMQ[index].lazy = EMPTY;
    RMQ[index].lazy_coef = 0;
  }
 
  inline void value_update(int index){ RMQ[index].value = RMQ[index*2+1].value + RMQ[index*2+2].value; }

  void _update(int a,int b,char opr,int v,int index,int L,int R){
    lazy_evaluate(index,L,R);
    if( b <= L || R <= a )return;
    if( a <= L && R <= b ){
      RMQ[index].lazy = opr; // 今いるノードに遅延を設定して処理をしてもらう
      if( opr == 'A' )      RMQ[index].lazy_coef += v; 
      else if( opr == 'S' ) RMQ[index].lazy_coef = v; 
      lazy_evaluate(index,L,R);
      return;
    }
    _update(a,b,opr,v,index*2+1,L,(L+R)/2);
    _update(a,b,opr,v,index*2+2,(L+R)/2,R);
    value_update(index);
  }

  void update(int a,int b,char opr,short v){ _update(a,b,opr,v,0,0,limit); } 

  int _query(int a,int b,int index,int L,int R){
    lazy_evaluate(index,L,R); 
    if( b <= L || R <= a ) return 0;
    if( a <= L && R <= b ) return RMQ[index].value;
    short tmp1 = _query(a,b,index*2+1,L,(L+R)/2);
    short tmp2 = _query(a,b,index*2+2,(L+R)/2,R);
    short ret = tmp1+tmp2;
    value_update(index); //ここまでくると子の値が正しくなっているのでその和をとって今いるノードにも正しい値をいれる
    return ret;
  }

  // [a,b) の総和、最小値、最大値を返す
  short query(int a,int b) { return _query(a,b,0,0,limit); }

};

typedef pair<int,int> ii;
const int MAX_V = 1001;
struct Edge {
  int src,dst,depart,arrive;
};

int S,T,D,timeD,Rendezvous,timeRendezvous;

inline int toMinute(string s) { 
  int ret = ( s[3] - '0' ) * 10 + ( s[4] - '0' );
  return ret + ( ( s[0] - '0' ) * 10 + ( s[1] - '0' ) ) * 60;
}

struct Data {
  int cur,time;
  bool operator < ( const Data &data ) const { 
    if( time != data.time ) return time > data.time;
    return cur > data.cur;
  }
};

const int MAX_T = 1441;
vector<Edge> G[MAX_V],rG[MAX_V];
SegTree dp[MAX_V][2]; // dp[station][ 0 : from dept, 1 : to rendezvous] := reachable?
vector<vector<bool> > used;

void compute(vector<int> &N,vector<vector<ii> > &KT){
  rep(i,S) rep(j,2) {
    dp[i][j].init(MAX_T);
    dp[i][j].build();
  }
  
  // dept to other station
  used.clear();
  used.resize(S,vector<bool>(MAX_T,false));
  dp[D][0].update(timeD,MAX_T,'S',1);
  used[D][timeD] = true;
  priority_queue<Data> Q;
  Q.push((Data){D,timeD});
  while( !Q.empty() ){
    Data data = Q.top(); Q.pop();
    rep(i,(int)G[data.cur].size()){
      if( data.time > G[data.cur][i].depart ) continue;
      int next = G[data.cur][i].dst;
      int arrive = G[data.cur][i].arrive;
      if( !used[next][arrive] ) {
        used[next][arrive] = true;
        dp[next][0].update(arrive,1500,'S',1);
        Q.push((Data){next,arrive});
      }
    }
  }

  // each station to ランデヴー
  rep(i,used.size()) rep(j,used[i].size()) used[i][j] = false;
  dp[Rendezvous][1].update(0,timeRendezvous+1,'S',1);
  used[Rendezvous][timeRendezvous] = true;
  assert( Q.empty() );
  Q.push((Data){Rendezvous,timeRendezvous});
  while( !Q.empty() ){
    Data data = Q.top(); Q.pop();
    rep(i,(int)rG[data.cur].size()){
      if( data.time < rG[data.cur][i].depart ) continue;
      int prev = rG[data.cur][i].dst;
      int r_arrive = rG[data.cur][i].arrive;
      if( !used[prev][r_arrive] ){
        used[prev][r_arrive] = true;
        dp[prev][1].update(0,r_arrive+1,'S',1);
        Q.push((Data){prev,r_arrive});
      }
    }
  }
  int maxi = -1;
  rep(i,N.size()){
    rep(j,N[i]-1) {
      int f = KT[i][j].first, ft = KT[i][j].second;
      if( !dp[f][0].query(ft,ft+1) ) continue;
      REP(k,j+1,N[i]){
        int t = KT[i][k].first, tt = KT[i][k].second;
        int sleep = tt - ft;
        assert( sleep >= 1 );
        if( sleep <= maxi ) continue;
        if( dp[t][1].query(tt,tt+1) ) {
          maxi = max(maxi,sleep);
        }
      }
    }
  }
  
  if( maxi == -1 && D == Rendezvous && timeD <= timeRendezvous ) puts("0");
  else if( maxi == -1 ) puts("impossible");
  else printf("%d\n",maxi);
}


int main(){
  while( scanf("%d %d",&S,&T), S|T ){
    rep(i,S) G[i].clear(), rG[i].clear();
    rep(i,MAX_V) rep(j,2) dp[i][j].RMQ.clear();
    string temp;
    cin >> D >> temp;
    --D;
    timeD = toMinute(temp);
    cin >> Rendezvous >> temp;
    --Rendezvous;
    timeRendezvous = toMinute(temp);
    vector<int> N(T);
    vector<vector<ii> > KT(T,vector<ii>());
    rep(i,T){
      cin >> N[i];
      KT[i].resize(N[i]);
      rep(j,N[i]) {
        cin >> KT[i][j].first >> temp;
        --KT[i][j].first;
        KT[i][j].second = toMinute(temp);
      }
      rep(j,N[i]-1) {
        int f = KT[i][j].first  , ft = KT[i][j].second;
        int t = KT[i][j+1].first, tt = KT[i][j+1].second;
         G[f].push_back((Edge){f,t,ft,tt});
        rG[t].push_back((Edge){t,f,tt,ft});
      }
    }

    compute(N,KT);
    
  }
  return 0;
}
accuracy: 1
time_ms: 2250
memory_kb: 62088
final_rank: 8

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

const int INF = INT_MAX / 2;

class Edge{
public:
    int to, time1, time2;
    Edge(int to0, int time01, int time02){
        to = to0;
        time1 = time01;
        time2 = time02;
    }
};

int toInt(string& s)
{
    return atoi(s.substr(0,2).c_str()) * 60 + atoi(s.substr(3, 2).c_str());
}

int main()
{
    for(;;){
        int s, t; // 駅の数、電車の数
        cin >> s >> t;
        if(s == 0)
            return 0;

        int start, goal;         // 出発地、目的地
        int startTime, goalTime; // 出発時間、待ち合わせの時間
        string tmp1, tmp2;
        cin >> start >> tmp1 >> goal >> tmp2;
        startTime = toInt(tmp1);
        goalTime = toInt(tmp2);

        vector<int> n(t);             // n[i]       : 電車iが停まる駅の数
        vector<vector<int> > stop(t); // stop[i][j] : 電車iがj番目に停まる駅
        vector<vector<int> > time(t); // time[i][j] : 電車iがj番目に停まる時間
        vector<vector<Edge> > edges(s+1);
        vector<vector<Edge> > invEdges(s+1);
        for(int i=0; i<t; ++i){
            cin >> n[i];
            stop[i].resize(n[i]);
            time[i].resize(n[i]);

            for(int j=0; j<n[i]; ++j){
                string tmp;
                cin >> stop[i][j] >> tmp;
                time[i][j] = toInt(tmp);
            }
            for(int j=1; j<n[i]; ++j){
                edges[stop[i][j-1]].push_back(Edge(stop[i][j], time[i][j-1], time[i][j]));
                invEdges[stop[i][j]].push_back(Edge(stop[i][j-1], time[i][j-1], time[i][j]));
            }
        }

        vector<int> minTime(s+1, INF); // minTime[i] : 出発地から駅iに向かったとき、駅iに到着する最も早い時間
        vector<int> maxTime(s+1, -1);  // maxTime[i] : 駅iから目的地に向かったとき、駅iを出発しなければならない最も遅い時間

        multimap<int, int> mm;
        mm.insert(make_pair(startTime, start));
        minTime[start] = startTime;
        while(!mm.empty()){
            int currTime = mm.begin()->first;
            int pos = mm.begin()->second;
            mm.erase(mm.begin());
            if(currTime > minTime[pos])
                continue;

            for(unsigned i=0; i<edges[pos].size(); ++i){
                Edge e = edges[pos][i];
                if(currTime <= e.time1 && e.time2 < minTime[e.to]){
                    minTime[e.to] = e.time2;
                    mm.insert(make_pair(e.time2, e.to));
                }
            }
        }

        mm.insert(make_pair(-goalTime, goal));
        maxTime[goal] = goalTime;
        while(!mm.empty()){
            int currTime = - mm.begin()->first;
            int pos = mm.begin()->second;
            mm.erase(mm.begin());
            if(currTime < maxTime[pos])
                continue;

            for(unsigned i=0; i<invEdges[pos].size(); ++i){
                Edge e = invEdges[pos][i];
                if(currTime >= e.time2 && e.time1 > maxTime[e.to]){
                    maxTime[e.to] = e.time1;
                    mm.insert(make_pair(-e.time1, e.to));
                }
            }
        }

        int ret = -1;
        if(start == goal && startTime <= goalTime)
            ret = 0;
        for(int i=0; i<t; ++i){
            for(int j=0; j<n[i]; ++j){
                for(int k=j+1; k<n[i]; ++k){
                    if(minTime[stop[i][j]] <= time[i][j] && time[i][k] <= maxTime[stop[i][k]])
                        ret = max(ret, time[i][k] - time[i][j]);
                }
            }
        }
        if(ret == -1)
            cout << "impossible" << endl;
        else
            cout << ret << endl;
    }
}
accuracy: 1
time_ms: 300
memory_kb: 5228
final_rank: 1

code_snippet: #include<cstdio>
#include<vector>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

int readtime(){
	int hh,mm; scanf("%d:%d",&hh,&mm);
	return 60*hh+mm;
}

int main(){
	for(int n,m;scanf("%d%d",&n,&m),n;){
		int s; scanf("%d",&s); s--;
		int s_time=readtime();
		int g; scanf("%d",&g); g--;
		int g_time=readtime();

		vector< pair<int,int> > seq[100]; // seq[i] := ( 電車 i の運行予定 )
		rep(i,m){
			int sz; scanf("%d",&sz);
			seq[i].resize(sz);
			rep(j,sz){
				int u; scanf("%d",&u); u--;
				seq[i][j]=make_pair(readtime(),u);
			}
			sort(seq[i].begin(),seq[i].end());
		}

		// train[t][u] := ( 時刻 t に駅 u から発車する電車の情報 )
		static vector< pair<int,int> > train[1440][1000];
		rep(t,1440) rep(u,n) train[t][u].clear();
		rep(i,m){
			rep(j,seq[i].size()){
				int t=seq[i][j].first;
				int u=seq[i][j].second;
				train[t][u].push_back(make_pair(i,j));
			}
		}

		static int dp[1440][1000];
		rep(t,1440) rep(u,n) dp[t][u]=-1; // -1 は到達不可能の意味
		dp[s_time][s]=0;
		rep(t,1439) rep(u,n) if(dp[t][u]!=-1) {
			 dp[t+1][u]=max(dp[t+1][u],dp[t][u]); // 電車に乗らずにその駅で待つ
			 rep(i,train[t][u].size()){ // 電車に乗る
				int id=train[t][u][i].first;
				for(int j=train[t][u][i].second+1;j<seq[id].size();j++){
					int t_next=seq[id][j].first;
					int u_next=seq[id][j].second;
					dp[t_next][u_next]=max(dp[t_next][u_next],max(dp[t][u],t_next-t));
				}
			 }
		}

		int ans=-1;
		rep(t,g_time+1) ans=max(ans,dp[t][g]);
		if(ans==-1) puts("impossible");
		else        printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 720
memory_kb: 26000
final_rank: 5

code_snippet: #include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

class Edge
{
public:
	int d,i,o;
	Edge(int d, int i, int o)
	:d(d),i(i),o(o)
	{}
};

class State
{
public:
	int n,t;
	State(int n, int t)
	:n(n),t(t)
	{}
	
	bool operator<(const State& s) const
	{
		return t>s.t;
	}
};

typedef vector<Edge> Edges;
typedef pair<vector<int>, vector<int> > Train;

int input()
{
	string s;
	cin >> s;
	
	return ((s[0]-'0')*10+(s[1]-'0'))*60+((s[3]-'0')*10+(s[4]-'0'));
}

int beg[1000], end[1000];

int dijk(int S, int st, int lim, vector<Edges>& eg, bool f)
{
	bool v[1000]={0};
	priority_queue<State> q;
	q.push(State(S,st));
	
	while(!q.empty())
	{
		State s=q.top(); q.pop();
		if(s.t>lim) break;
		
		if(v[s.n]) continue;
		v[s.n]=1;
		
		if(f) beg[s.n]=s.t;
		else  end[s.n]=-s.t+24*60;
		
		for(int i=0; i<eg[s.n].size(); i++)
		{
			Edge e=eg[s.n][i];
			if(v[e.d]) continue;
			if(s.t > e.i) continue;
			
			q.push(State(e.d, e.o));
		}
	}
	
	return -1;
}

int main()
{
	int S,T;
	while(cin >> S >> T, (S||T))
	{
		int src,dst,st,dt;
		cin >> src; st=input();
		cin >> dst; dt=input();
		
		src--; dst--;
		
		vector<Edges> eg(1000),reg(1000);
		vector<Train> trains(100);
		
		for(int i=0; i<T; i++)
		{
			int N;
			cin >> N;
			vector<int> p,t;
			for(int j=0; j<N; j++)
			{
				int a,b;
				cin >> a; b=input();
				a--;
				
				p.push_back(a);
				t.push_back(b);
			}
			trains[i]=make_pair(p,t);
			
			for(int j=0; j<N-1; j++)
			{
				int s=p[j], d=p[j+1];
				int a=t[j], b=t[j+1];
				eg[s].push_back(Edge(d,a,b));
				reg[d].push_back(Edge(s,24*60-b, 24*60-a));
			}
		}
		
		for(int i=0; i<S; i++)
		{
			beg[i]=9999;
			end[i]=-1;
		}
		
		dijk(src,st,dt,eg,1);
	    dijk(dst,24*60-dt,24*60-st,reg,0);
		
		int ret=-1;
		if(src==dst&&st<=dt) ret=0;
		
		for(int i=0; i<T; i++)
		{
			int lo=9999,hi=-1;
			for(int j=0; j<trains[i].first.size(); j++)
			{
				int p=trains[i].first[j], t=trains[i].second[j];
				if(beg[p] <= t) lo=min(j,lo);
				if(end[p] >= t) hi=max(j,hi);
			}
			
			if(lo==9999||hi==-1) continue;
			ret=max(ret, trains[i].second[hi]-trains[i].second[lo]);
		}
		if(ret==-1) cout << "impossible" << endl;
		else cout << ret << endl;

	}
}
accuracy: 1
time_ms: 430
memory_kb: 5292
final_rank: 3

code_snippet: #include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define pb         push_back

const int N = 1000;
const int inf =(1<<20);
class Edge{
public:
  int st,gt;
  int to;
};

class Rail{
public:
  int p,t;
};

class state{
public:
  int now;
  int time;
  bool operator<(const state & a)const{
    return time > a.time;
  }
  bool operator>(const state & a)const{
    return time < a.time;
  }
};


void go(int n,int s,int st,vector<Edge> *edge,bool isrev,int *cost){
  priority_queue<state> Q;
  priority_queue<state,vector<state>,greater<state> > RQ;
  if (!isrev)Q.push((state){s,st});
  else RQ.push((state){s,st});
  
  while(!Q.empty() || !RQ.empty()){
    state now;
    if (!isrev){
      now=Q.top(),Q.pop();
    }else{
      now = RQ.top(),RQ.pop();
    }
    if (cost[now.now] != inf)continue;
    //if (cost[now.now] == inf)
      cost[now.now] = now.time;
    /*
    else {
      if (isrev){
	
	if (now.time > cost[now.now])exit(1);
	else continue;
      }else {
	//	cout << now.now+1 <<" " <<now.time <<" " << cost[now.now] << endl;
	if (now.time < cost[now.now])exit(1);
	else continue;
      }
    }
    */
    rep(i,edge[now.now].size()){
      if (isrev){
	if (now.time < edge[now.now][i].st)continue;
	RQ.push((state){edge[now.now][i].to,edge[now.now][i].gt});
      }else{
	if (now.time > edge[now.now][i].st)continue;
	Q.push((state){ edge[now.now][i].to,edge[now.now][i].gt});
      }
    }
  }
}

main(){
  int n;
  int line;
  int scost[N],tcost[N];
  vector<Edge> edge[N];
  vector<Edge> rev[N];
  vector<Rail > in[100]; 
  while(cin>>n>>line && n){
    rep(i,n)tcost[i]=inf,scost[i]=inf;
    rep(i,n)edge[i].clear(),rev[i].clear();
    rep(i,line)in[i].clear();
    int s,sh,sm,d,dh,dm;
    char dummy;
    cin>>s>>sh>>dummy>>sm>> d>>dh>>dummy>>dm;
    
    sh=sh*60+sm;
    dh=dh*60+dm;
    s--;
    d--;
    
    rep(i,line){
      int m;
      cin>>m;
      rep(j,m){
	int now,nh,nm;
	cin>>now>>nh>>dummy>>nm;
	now--;
	nh = nh*60+nm;
	in[i].push_back((Rail){now,nh});
      }
      
      rep(j,in[i].size()-1){
	edge[in[i][j  ].p].pb((Edge){in[i][j  ].t,in[i][j+1].t,in[i][j+1].p});
	rev[ in[i][j+1].p].pb((Edge){in[i][j+1].t,in[i][j  ].t,in[i][j  ].p});
      }
    }
    

    go(n,s,sh,edge,false,scost);
    go(n,d,dh,rev ,true ,tcost);

    /*
      cout << "begint"<<endl;
      cout << n << endl;
      cout <<"go"<<endl;
      rep(i,n)cout << scost[i] <<" ";cout << endl;
      cout << "rev " << endl;
      rep(i,n)cout << tcost[i] <<" ";cout << endl;
      cout << endl;
    */

    int ans = -1;
    if (scost[d] == inf){
      cout << "impossible"<<endl;
      continue;
    }
    if (s == d && sh <= dh)ans = 0;

    rep(i,line){
      int scan=-1,dcan=-1;
      rep(j,in[i].size()){
	if (scost[in[i][j].p] == inf)continue;
	if (scost[in[i][j].p] <= in[i][j].t){
	  scan=j;
	  break;
	}
      }
      
      for(int j=in[i].size()-1;j>=0 && j >scan;j--){
	if (tcost[in[i][j].p] == inf)continue;
	if (tcost[in[i][j].p] >= in[i][j].t){
	  dcan=j;
	  break;
	}
      }

      if (scan == -1 || dcan == -1)continue;

      ans = max(ans,in[i][dcan].t-in[i][scan].t);
    }
    
    if (ans == -1)cout << "impossible"<<endl;
    else cout << ans << endl;
    
  }
}
accuracy: 1
time_ms: 400
memory_kb: 5844
final_rank: 2