// yukicoder No.5023 Airlines Optimization // Fixed hyperparams (behavior same except faster): // candDest[i] = nearest 18 + top-pop 26 // origin limit = 47 (all cities) // DP start cities = 47 (all cities) // // Compile: g++ -O2 -std=c++17 -pipe -static -s main.cpp -o main #include using namespace std; static constexpr int MAXN = 47; static constexpr int SLOT_MIN = 5; static constexpr int DAY_START_MIN = 6 * 60; // 06:00 static constexpr int DAY_END_MIN = 21 * 60; // 21:00 static constexpr int TS = (DAY_END_MIN - DAY_START_MIN) / SLOT_MIN + 1; // 181 static constexpr int V = MAXN * TS; // ===== Fixed hyperparameters ===== static constexpr int ORIGIN_USE = 47; static constexpr int START_USE = 47; static constexpr int NEAR_CAND = 18; static constexpr int POP_CAND = 26; static constexpr int K_FIXED = 25; static constexpr int M_FIXED = 400; // Targets: 11:00, 11:30, ..., 21:00 (21 values) static constexpr int TGT = 21; struct FlightOut { int a, b; int dep_t, arr_t; // time index }; static inline int timeToIdx(int minute) { return (minute - DAY_START_MIN) / SLOT_MIN; } static inline int idxToTime(int idx) { return DAY_START_MIN + idx * SLOT_MIN; } static inline string fmtTimeIdx(int idx) { int m = idxToTime(idx); int hh = m / 60, mm = m % 60; char buf[6]; snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm); return string(buf); } static inline int parseTimeStr(const string& s) { int hh = (s[0]-'0')*10 + (s[1]-'0'); int mm = (s[3]-'0')*10 + (s[4]-'0'); return hh*60 + mm; } // ===== globals ===== static uint32_t popW[MAXN]; static int N, R; static int durSlot[MAXN][MAXN]; static double distMat[MAXN][MAXN]; static bool validPair[MAXN][MAXN]; // earliest[d][t][c] (time-major for cache) static uint16_t earliestSq[MAXN][TS][MAXN]; static uint16_t earliestCi[MAXN][TS][MAXN]; static constexpr uint16_t INF16 = 65535; // latest[o][d][deadline] (same as before) static int16_t latestSq[MAXN][MAXN][TS]; static int16_t latestCi[MAXN][MAXN][TS]; static int16_t s_sq[MAXN][MAXN][TGT]; static int16_t s_ci[MAXN][MAXN][TGT]; // reachMask[vtx][ti] : destinations reachable by target ti from vtx static uint64_t reachMask[V][TGT]; static bool oldWin[MAXN][MAXN][TGT]; // flipMask[oi][s][ti] (IMPORTANT: ti contiguous now) static uint64_t flipMask[ORIGIN_USE][TS][TGT]; static int tgtIdx[TGT]; static int firstTiTime[TS]; // first target index whose deadline >= timeIdx (or TGT) // ===== sumW(mask) tables ===== static uint64_t T0[1<<16]; static uint64_t T1[1<<16]; static uint64_t T2[1<<15]; static inline void buildWeightTables(const uint32_t* w) { T0[0]=0; for (uint32_t m=1; m<(1u<<16); m++) { uint32_t b = __builtin_ctz(m); T0[m] = T0[m & (m-1)] + (uint64_t)w[b]; } T1[0]=0; for (uint32_t m=1; m<(1u<<16); m++) { uint32_t b = __builtin_ctz(m); T1[m] = T1[m & (m-1)] + (uint64_t)w[16 + b]; } T2[0]=0; for (uint32_t m=1; m<(1u<<15); m++) { uint32_t b = __builtin_ctz(m); T2[m] = T2[m & (m-1)] + (uint64_t)w[32 + b]; } } static inline uint64_t sumW_mask(uint64_t mask) { uint32_t a = (uint32_t)(mask & 0xFFFFull); uint32_t b = (uint32_t)((mask >> 16) & 0xFFFFull); uint32_t c = (uint32_t)((mask >> 32) & 0x7FFFull); return T0[a] + T1[b] + T2[c]; } // ===== CSR adjacency (contiguous edges per u) ===== template struct CSRAdj { int E = 0; int u[MAXE]; uint8_t toCity[MAXE]; uint8_t arrT[MAXE]; int start[V+1]; // size V+1 uint8_t bTo[MAXE]; uint8_t bArr[MAXE]; void init() { E = 0; } inline void addEdge(int uV, int vCity, int at) { u[E] = uV; toCity[E] = (uint8_t)vCity; arrT[E] = (uint8_t)at; ++E; } void build() { static int cnt[V]; static int cur[V]; memset(cnt, 0, sizeof(cnt)); for (int i=0;i sqAdj; static CSRAdj<20000> ciAdj; // ===== build earliest + latest ===== static void buildEarliestAndLatest(const CSRAdj<20000>& adj, uint16_t earliest[MAXN][TS][MAXN], int16_t latest[MAXN][MAXN][TS]) { // earliest[d][t][c] = min arrival time at d starting from (c,t) for (int d=0; d=0; --t) { uint16_t* row = earliest[d][t]; uint16_t* rowWait = (t+1 < TS) ? earliest[d][t+1] : nullptr; for (int c=0; c& adj, uint16_t earliest[MAXN][TS][MAXN], int16_t latest[MAXN][MAXN][TS]) { for (int d=0; d=0; --t) { uint16_t* row = earliest[d][t]; uint16_t* rowWait = (t+1 < TS) ? earliest[d][t+1] : nullptr; for (int c=0; c s_sq[o][d][ti]); } } } } // build flipMask[oi][s][ti] static void buildFlipMaskForOrigins(const vector& originsUsed) { for (int oi=0; oi<(int)originsUsed.size(); oi++) { int o = originsUsed[oi]; for (int ti=0; ti& originsUsed) { for (int u=0; u solveOnePlaneDP(const vector>& candDest, const vector& startCities) { static __int128 dp[V]; static int prevv[V]; const __int128 NEG = -((__int128)1<<120); for (int i=0;i bestVal) { bestVal=cur; bestVtx=u; } // wait if (t+1 < TS) { int v = u+1; if (cur > dp[v]) { dp[v]=cur; prevv[v]=u; } } // flight candidates (order preserved: candDest[c] is sorted asc) const auto& cd = candDest[c]; for (int j: cd) { int at = t + durSlot[c][j]; if (at >= TS) continue; int v = j*TS + at; uint64_t g = edgeGainUV(u, v, at); __int128 nv = cur + (__int128)g; if (nv > dp[v]) { dp[v]=nv; prevv[v]=u; } } } } for (int u=0;u bestVal) { bestVal=dp[u]; bestVtx=u; } } vector revFlights; int cur = bestVtx; while (cur!=-1) { int p = prevv[cur]; if (p==-1) break; int pc = p/TS, pt = p%TS; int cc = cur/TS, ct = cur%TS; if (pc != cc) revFlights.push_back(FlightOut{pc, cc, pt, ct}); cur = p; } reverse(revFlights.begin(), revFlights.end()); return revFlights; } // ===== debug score ===== static long long evalScoreEstimate() { __int128 vci=0, vsq=0; for (int o=0;o s_sq[o][d][ti]) vci += ww; else vsq += ww; } } } if (vci+vsq==0) return 0; long double S = (long double)vci / (long double)(vci+vsq); return (long long)floor(1e6L * S + 1e-12L); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> N >> R; vector xs(N), ys(N); for (int i=0;i> xs[i] >> ys[i] >> popW[i]; for (int i=0;i= thr); if (i==j) durSlot[i][j]=0; else { double raw = 60.0 * d / 800.0 + 40.0; int q = (int)ceil(raw / 5.0 - 1e-12); durSlot[i][j] = q; // in 5-min slots } } } buildWeightTables(popW); int M; cin >> M; sqAdj.init(); for (int k=0;k> a >> ss >> b >> tt; --a; --b; int s = timeToIdx(parseTimeStr(ss)); int t = timeToIdx(parseTimeStr(tt)); sqAdj.addEdge(a*TS + s, b, t); } sqAdj.build(); int K; cin >> K; (void)K; ciAdj.init(); // Square: earliest/latest/targets buildEarliestAndLatest_sq(sqAdj, earliestSq, latestSq); buildTargetsFromLatest(latestSq, s_sq); // population order vector popOrder(N); iota(popOrder.begin(), popOrder.end(), 0); sort(popOrder.begin(), popOrder.end(), [&](int a,int b){ return popW[a]>popW[b]; }); // candDest: nearest 18 + top-pop 26, then sort+unique (same behavior pattern) vector> candDest(N); for (int i=0;i> near; near.reserve(N-1); for (int j=0;j cand; cand.reserve(min(NEAR_CAND, N-1) + min(POP_CAND, N-1) + 4); int takeNear = min(NEAR_CAND, N-1); for (int k=0; k<(int)near.size() && (int)cand.size() startCities; for (int i=0;i originsUsed; for (int i=0;i> routes(K_FIXED); for (int plane=0; plane