結果
問題 | No.5010 Better Mo's Algorithm is Needed!! (Unweighted) |
ユーザー | tomerun |
提出日時 | 2022-12-17 20:26:49 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 4,942 ms / 5,000 ms |
コード長 | 12,088 bytes |
コンパイル時間 | 1,330 ms |
実行使用メモリ | 86,548 KB |
スコア | 18,900,266,925 |
最終ジャッジ日時 | 2022-12-17 20:37:34 |
合計ジャッジ時間 | 642,686 ms |
ジャッジサーバーID (参考情報) |
judge11 / judge10 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 4,940 ms
86,176 KB |
testcase_01 | AC | 4,929 ms
86,152 KB |
testcase_02 | AC | 4,930 ms
86,452 KB |
testcase_03 | AC | 4,926 ms
86,212 KB |
testcase_04 | AC | 4,923 ms
86,164 KB |
testcase_05 | AC | 4,922 ms
86,452 KB |
testcase_06 | AC | 4,934 ms
86,168 KB |
testcase_07 | AC | 4,924 ms
86,164 KB |
testcase_08 | AC | 4,924 ms
86,364 KB |
testcase_09 | AC | 4,929 ms
86,104 KB |
testcase_10 | AC | 4,940 ms
86,236 KB |
testcase_11 | AC | 4,925 ms
86,412 KB |
testcase_12 | AC | 4,924 ms
86,196 KB |
testcase_13 | AC | 4,929 ms
86,172 KB |
testcase_14 | AC | 4,931 ms
86,452 KB |
testcase_15 | AC | 4,931 ms
86,144 KB |
testcase_16 | AC | 4,921 ms
86,200 KB |
testcase_17 | AC | 4,928 ms
86,380 KB |
testcase_18 | AC | 4,919 ms
86,188 KB |
testcase_19 | AC | 4,933 ms
86,256 KB |
testcase_20 | AC | 4,932 ms
86,288 KB |
testcase_21 | AC | 4,934 ms
86,172 KB |
testcase_22 | AC | 4,935 ms
86,316 KB |
testcase_23 | AC | 4,926 ms
86,424 KB |
testcase_24 | AC | 4,922 ms
86,116 KB |
testcase_25 | AC | 4,936 ms
86,268 KB |
testcase_26 | AC | 4,937 ms
86,384 KB |
testcase_27 | AC | 4,934 ms
86,224 KB |
testcase_28 | AC | 4,926 ms
86,284 KB |
testcase_29 | AC | 4,926 ms
86,368 KB |
testcase_30 | AC | 4,928 ms
86,244 KB |
testcase_31 | AC | 4,928 ms
86,208 KB |
testcase_32 | AC | 4,926 ms
86,440 KB |
testcase_33 | AC | 4,938 ms
86,160 KB |
testcase_34 | AC | 4,927 ms
86,200 KB |
testcase_35 | AC | 4,924 ms
86,372 KB |
testcase_36 | AC | 4,924 ms
86,156 KB |
testcase_37 | AC | 4,928 ms
86,172 KB |
testcase_38 | AC | 4,936 ms
86,492 KB |
testcase_39 | AC | 4,925 ms
86,244 KB |
testcase_40 | AC | 4,936 ms
86,096 KB |
testcase_41 | AC | 4,939 ms
86,484 KB |
testcase_42 | AC | 4,923 ms
86,252 KB |
testcase_43 | AC | 4,929 ms
86,224 KB |
testcase_44 | AC | 4,930 ms
86,276 KB |
testcase_45 | AC | 4,924 ms
86,244 KB |
testcase_46 | AC | 4,927 ms
86,168 KB |
testcase_47 | AC | 4,933 ms
86,384 KB |
testcase_48 | AC | 4,935 ms
86,232 KB |
testcase_49 | AC | 4,930 ms
86,164 KB |
testcase_50 | AC | 4,930 ms
86,336 KB |
testcase_51 | AC | 4,923 ms
86,208 KB |
testcase_52 | AC | 4,931 ms
86,256 KB |
testcase_53 | AC | 4,923 ms
86,400 KB |
testcase_54 | AC | 4,928 ms
86,172 KB |
testcase_55 | AC | 4,923 ms
86,204 KB |
testcase_56 | AC | 4,931 ms
86,452 KB |
testcase_57 | AC | 4,935 ms
86,312 KB |
testcase_58 | AC | 4,920 ms
86,092 KB |
testcase_59 | AC | 4,933 ms
86,484 KB |
testcase_60 | AC | 4,927 ms
86,288 KB |
testcase_61 | AC | 4,939 ms
86,176 KB |
testcase_62 | AC | 4,925 ms
86,416 KB |
testcase_63 | AC | 4,926 ms
86,304 KB |
testcase_64 | AC | 4,927 ms
86,180 KB |
testcase_65 | AC | 4,931 ms
86,408 KB |
testcase_66 | AC | 4,924 ms
86,276 KB |
testcase_67 | AC | 4,920 ms
86,108 KB |
testcase_68 | AC | 4,929 ms
86,516 KB |
testcase_69 | AC | 4,933 ms
86,176 KB |
testcase_70 | AC | 4,929 ms
86,236 KB |
testcase_71 | AC | 4,927 ms
86,432 KB |
testcase_72 | AC | 4,933 ms
86,192 KB |
testcase_73 | AC | 4,919 ms
86,304 KB |
testcase_74 | AC | 4,928 ms
86,284 KB |
testcase_75 | AC | 4,930 ms
86,160 KB |
testcase_76 | AC | 4,928 ms
86,172 KB |
testcase_77 | AC | 4,925 ms
86,548 KB |
testcase_78 | AC | 4,929 ms
86,248 KB |
testcase_79 | AC | 4,931 ms
86,124 KB |
testcase_80 | AC | 4,927 ms
86,388 KB |
testcase_81 | AC | 4,924 ms
86,304 KB |
testcase_82 | AC | 4,930 ms
86,164 KB |
testcase_83 | AC | 4,921 ms
86,440 KB |
testcase_84 | AC | 4,920 ms
86,044 KB |
testcase_85 | AC | 4,932 ms
86,308 KB |
testcase_86 | AC | 4,920 ms
86,436 KB |
testcase_87 | AC | 4,925 ms
86,216 KB |
testcase_88 | AC | 4,932 ms
86,176 KB |
testcase_89 | AC | 4,928 ms
86,428 KB |
testcase_90 | AC | 4,941 ms
86,144 KB |
testcase_91 | AC | 4,925 ms
86,216 KB |
testcase_92 | AC | 4,940 ms
86,536 KB |
testcase_93 | AC | 4,936 ms
86,204 KB |
testcase_94 | AC | 4,938 ms
86,036 KB |
testcase_95 | AC | 4,935 ms
86,440 KB |
testcase_96 | AC | 4,928 ms
86,252 KB |
testcase_97 | AC | 4,927 ms
86,196 KB |
testcase_98 | AC | 4,935 ms
86,424 KB |
testcase_99 | AC | 4,927 ms
86,280 KB |
testcase_100 | AC | 4,933 ms
86,244 KB |
testcase_101 | AC | 4,942 ms
86,388 KB |
testcase_102 | AC | 4,929 ms
86,224 KB |
testcase_103 | AC | 4,928 ms
86,196 KB |
testcase_104 | AC | 4,928 ms
86,520 KB |
testcase_105 | AC | 4,939 ms
86,064 KB |
testcase_106 | AC | 4,923 ms
86,096 KB |
testcase_107 | AC | 4,933 ms
86,408 KB |
testcase_108 | AC | 4,923 ms
86,232 KB |
testcase_109 | AC | 4,926 ms
86,252 KB |
testcase_110 | AC | 4,927 ms
86,396 KB |
testcase_111 | AC | 4,936 ms
86,216 KB |
testcase_112 | AC | 4,924 ms
86,152 KB |
testcase_113 | AC | 4,934 ms
86,392 KB |
testcase_114 | AC | 4,933 ms
86,112 KB |
testcase_115 | AC | 4,939 ms
86,304 KB |
testcase_116 | AC | 4,927 ms
86,456 KB |
testcase_117 | AC | 4,920 ms
86,212 KB |
testcase_118 | AC | 4,925 ms
86,288 KB |
testcase_119 | AC | 4,926 ms
86,348 KB |
ソースコード
#include <algorithm> #include <utility> #include <vector> #include <iostream> #include <array> #include <numeric> #include <memory> #include <functional> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <sys/time.h> #ifdef LOCAL #ifndef NDEBUG #define MEASURE_TIME #define DEBUG #endif #else #define NDEBUG // #define DEBUG #endif #include <cassert> using namespace std; using u8=uint8_t; using u16=uint16_t; using u32=uint32_t; using u64=uint64_t; using i64=int64_t; using ll=int64_t; using ull=uint64_t; using vi=vector<int>; using vvi=vector<vi>; namespace { constexpr ll TL = 4900; inline ll get_time() { struct timeval tv; gettimeofday(&tv, NULL); ll result = tv.tv_sec * 1000LL + tv.tv_usec / 1000LL; return result; } const ll start_time = get_time(); // msec inline ll get_elapsed_msec() { return get_time() - start_time; } inline bool reach_time_limit() { return get_elapsed_msec() >= TL; } struct XorShift { uint32_t x,y,z,w; static const double TO_DOUBLE; XorShift() { x = 123456789; y = 362436069; z = 521288629; w = 88675123; } uint32_t nextUInt(uint32_t n) { uint32_t t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); return w % n; } uint32_t nextUInt() { uint32_t t = x ^ (x << 11); x = y; y = z; z = w; return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); } double nextDouble() { return nextUInt() * TO_DOUBLE; } }; const double XorShift::TO_DOUBLE = 1.0 / (1LL << 32); struct Counter { vector<ull> cnt; void add(int i) { if (i >= cnt.size()) { cnt.resize(i+1); } ++cnt[i]; } void print() { cerr << "counter:["; for (int i = 0; i < cnt.size(); ++i) { cerr << cnt[i] << ", "; if (i % 10 == 9) cerr << endl; } cerr << "]" << endl; } }; struct Timer { vector<ull> at; vector<ull> sum; void start(int i) { if (i >= at.size()) { at.resize(i+1); sum.resize(i+1); } at[i] = get_time(); } void stop(int i) { sum[i] += get_time() - at[i]; } void print() { cerr << "timer:["; for (int i = 0; i < at.size(); ++i) { cerr << sum[i] << ", "; if (i % 10 == 9) cerr << endl; } cerr << "]" << endl; } }; } #ifdef MEASURE_TIME #define START_TIMER(i) (timer.start(i)) #define STOP_TIMER(i) (timer.stop(i)) #define PRINT_TIMER() (timer.print()) #define ADD_COUNTER(i) (counter.add(i)) #define PRINT_COUNTER() (counter.print()) #else #define START_TIMER(i) #define STOP_TIMER(i) #define PRINT_TIMER() #define ADD_COUNTER(i) #define PRINT_COUNTER() #endif #ifdef DEBUG #define debug(format, ...) fprintf(stderr, format, __VA_ARGS__) #define debugStr(str) fprintf(stderr, str) #define debugln() fprintf(stderr, "\n") #else #define debug(format, ...) #define debugStr(str) #define debugln() #endif template<class T> constexpr inline T sq(T v) { return v * v; } void debug_vec(const vi& vec) { debugStr("["); for (int i = 0; i < vec.size(); ++i) { debug("%d ", vec[i]); } debugStr("]"); } XorShift rnd; Timer timer; Counter counter; //////// end of template //////// constexpr int N = 200000; constexpr int Q = 200000; constexpr ll INF = 1ll << 62; int WT, ST; array<int64_t, N> W; array<int64_t, N + 1> WS; array<int, Q> L; array<int, Q> R; constexpr int PART = 51; constexpr int DP_BIT = 3; constexpr int DP_SKIP = -1; ll dp[Q + 1][1 << DP_BIT][DP_BIT]; ll dp_prev[Q + 1][1 << DP_BIT][DP_BIT]; ll calc_cost(int l0, int r0, int l1, int r1) { ll cost = WS[max(l0, l1)] - WS[min(l0, l1)]; cost += WS[max(r0, r1) + 1] - WS[min(r0, r1) + 1]; return cost; } vi solve_dp(const vvi& buckets) { for (int i = 0; i < Q; ++i) { for (int j = 0; j < (1 << DP_BIT); ++j) { fill(dp[i][j], dp[i][j] + DP_BIT, INF); } } vi ranges = buckets[0]; for (int i = 1; i < PART; ++i) { ranges.insert(ranges.end(), buckets[i].begin(), buckets[i].end()); } for (int i = 0; i < DP_BIT; ++i) { dp[0][1 << i][i] = WS[R[ranges[0]] + 1] - WS[L[ranges[0]]]; } for (int j = 0; j < (1 << DP_BIT); ++j) { int pk = j; while (pk) { int k = __builtin_ctz(pk); pk &= pk - 1; int left = L[ranges[k]]; int right = R[ranges[k]]; int nl = ((1 << DP_BIT) - 1) ^ j; while (nl) { int l = __builtin_ctz(nl); nl &= nl - 1; int left1 = L[ranges[l]]; int right1 = R[ranges[l]]; ll cost = WS[max(left, left1)] - WS[min(left, left1)]; cost += WS[max(right, right1) + 1] - WS[min(right, right1) + 1]; int next_bit = j | (1 << l); if (dp[0][next_bit][l] > dp[0][j][k] + cost) { dp[0][next_bit][l] = dp[0][j][k] + cost; dp_prev[0][next_bit][l] = k; if ((j & 1) && l > 0 && dp[1][next_bit >> 1][l - 1] > dp[0][next_bit][l]) { dp[1][next_bit >> 1][l - 1] = dp[0][next_bit][l]; dp_prev[1][next_bit >> 1][l - 1] = DP_SKIP; } } } } } for (int i = 1; i <= Q - DP_BIT; ++i) { for (int j = 0; j < (1 << (DP_BIT - 1)); ++j) { int pk = j; while (pk) { int k = __builtin_ctz(pk); pk &= pk - 1; if ((j & 1) && k > 0 && dp[i + 1][j >> 1][k - 1] > dp[i][j][k]) { dp[i + 1][j >> 1][k - 1] = dp[i][j][k]; dp_prev[i + 1][j >> 1][k - 1] = DP_SKIP; } int left = L[ranges[i + k]]; int right = R[ranges[i + k]]; int l = DP_BIT - 1; int left1 = L[ranges[i + l]]; int right1 = R[ranges[i + l]]; ll cost = WS[max(left, left1)] - WS[min(left, left1)]; cost += WS[max(right, right1) + 1] - WS[min(right, right1) + 1]; int next_bit = j | (1 << l); if (dp[i][next_bit][l] > dp[i][j][k] + cost) { dp[i][next_bit][l] = dp[i][j][k] + cost; dp_prev[i][next_bit][l] = k; } if ((j & 1) && dp[i + 1][next_bit >> 1][l - 1] > dp[i][next_bit][l]) { dp[i + 1][next_bit >> 1][l - 1] = dp[i][next_bit][l]; dp_prev[i + 1][next_bit >> 1][l - 1] = DP_SKIP; } } } for (int j = (1 << (DP_BIT - 1)); j < (1 << DP_BIT); ++j) { int pk = j; while (pk) { int k = __builtin_ctz(pk); pk &= pk - 1; int left = L[ranges[i + k]]; int right = R[ranges[i + k]]; int nl = ((1 << DP_BIT) - 1) ^ j; while (nl) { int l = __builtin_ctz(nl); nl &= nl - 1; int left1 = L[ranges[i + l]]; int right1 = R[ranges[i + l]]; ll cost = WS[max(left, left1)] - WS[min(left, left1)]; cost += WS[max(right, right1) + 1] - WS[min(right, right1) + 1]; int next_bit = j | (1 << l); if (dp[i][next_bit][l] > dp[i][j][k] + cost) { dp[i][next_bit][l] = dp[i][j][k] + cost; dp_prev[i][next_bit][l] = k; } if ((j & 1) && dp[i + 1][next_bit >> 1][l - 1] > dp[i][next_bit][l]) { dp[i + 1][next_bit >> 1][l - 1] = dp[i][next_bit][l]; dp_prev[i + 1][next_bit >> 1][l - 1] = DP_SKIP; } } } } // if (i > Q - DP_BIT - 3) { // debug("i:%d\n", i); // for (int j = 0; j < 1 << DP_BIT; ++j) { // for (int k = 0; k < DP_BIT; ++k) { // debug("%d %d %lld\n", j, k, dp[i][j][k]); // } // } // } } int best_k = 0; for (int i = 0; i < DP_BIT; ++i) { if (dp[Q - DP_BIT][(1 << DP_BIT) - 1][i] < dp[Q - DP_BIT][(1 << DP_BIT) - 1][best_k]) { best_k = i; } } debug("best_cost:%lld\n", dp[Q - DP_BIT][(1 << DP_BIT) - 1][best_k]); vi ans; int ci = Q - DP_BIT; int cj = (1 << DP_BIT) - 1; int k = best_k; ans.push_back(ranges[ci + k]); while (ci > 0 || cj > 0) { int prev = dp_prev[ci][cj][k]; if (prev == DP_SKIP) { ci--; cj = (cj << 1) | 1; k++; // debugln(); } else { // debug("%d\n", prev); assert(cj | (1 << prev)); ans.push_back(ranges[ci + prev]); cj ^= 1 << k; k = prev; } } ans.pop_back(); reverse(ans.begin(), ans.end()); assert(ans.size() == Q); return ans; } bool accept(ll diff, double cooler) { if (diff <= 0) return true; double v = -diff * cooler; if (v < -9) return false; return rnd.nextDouble() < exp(v); } void solve_tsp(vi& ans) { constexpr int RANGE = 300; ll diff_sum = 0; int turn = 0; double cooler = 0.0005; while (true) { for (int i = 0; i < Q; ++i) { if ((i & 0xFFF) == 0) { ll elapsed = get_time() - start_time; if (elapsed > TL) { debug("turn:%d %d diff_sum:%lld\n", turn, i, diff_sum); return; } } int j = i + 2; int l00 = L[ans[i]]; int r00 = R[ans[i]]; int l01 = L[ans[i + 1]]; int r01 = R[ans[i + 1]]; ll diff_base = -calc_cost(l00, r00, l01, r01); for (int j = i + 2; j < i + RANGE && j < Q; ++j) { int l10 = L[ans[j]]; int r10 = R[ans[j]]; int l11 = L[ans[j + 1]]; int r11 = R[ans[j + 1]]; ll diff = diff_base - calc_cost(l10, r10, l11, r11); diff += calc_cost(l00, r00, l10, r10); diff += calc_cost(l01, r01, l11, r11); if (accept(diff, cooler)) { diff_sum += diff; reverse(ans.begin() + i + 1, ans.begin() + j + 1); l01 = L[ans[i + 1]]; r01 = R[ans[i + 1]]; diff_base = -calc_cost(l00, r00, l01, r01); } } } debug("diff_sum:%lld\n", diff_sum); turn += 1; cooler *= 3; } } int main() { int _; scanf("%d %d %d %d", &_, &_, &WT, &ST); for (int i = 0; i < N; ++i) { scanf("%lld", &W[i]); WS[i + 1] = WS[i] + W[i]; } for (int i = 0; i < Q; ++i) { scanf("%d %d", &L[i], &R[i]); L[i]--; R[i]--; } vector<vector<int>> buckets(PART); for (int i = 0; i < Q; ++i) { buckets[(ll)L[i] * PART / N].push_back(i); } for (int i = 0; i < PART; ++i) { if (i & 1) { sort(buckets[i].begin(), buckets[i].end(), [](int p0, int p1){ return R[p0] > R[p1]; }); } else { sort(buckets[i].begin(), buckets[i].end(), [](int p0, int p1){ return R[p0] < R[p1]; }); } } vi ans = solve_dp(buckets); solve_tsp(ans); int left = L[ans[0]]; int right = R[ans[0]]; ll ans_w = WS[right + 1] - WS[left]; for (int i = 1; i < Q; ++i) { int left1 = L[ans[i]]; int right1 = R[ans[i]]; ans_w += WS[max(left, left1)] - WS[min(left, left1)]; ans_w += WS[max(right, right1) + 1] - WS[min(right, right1) + 1]; left = left1; right = right1; } debug("ans_w=%lld\n", ans_w); debug("score=%lld\n", (ll)round(1000000000000000000ll / ans_w)); for (int p : ans) { printf("%d ", p + 1); } printf("\n"); }