#include <iostream> #include <vector> #include <deque> #include <map> #include <algorithm> #include <assert.h> using namespace std; typedef pair<short,short> interval; typedef deque<interval> intervals; int main() { ios_base::sync_with_stdio(false); int n; cin >> n; vector<vector<int> > C; C.resize(n); for(int i=0; i<n; i++) { C[i].resize(n); for(int j=i; j<n; j++) { cin >> C[i][j]; } } vector<interval> best; for(int i=0; i<n; i++) { for(int j=i; j<n; j++) { best.push_back({i,j}); } } sort(best.begin(), best.end(), [&C](const interval &a, const interval &b) -> bool { return C[a.first][a.second] < C[b.first][b.second]; } ); vector<interval> chosen, eliminated; map<int,vector<int>> chosen_ends, chosen_starts; auto choose = [&](int a, int b) { assert(C[a][b] >= 0); // cerr << "Choosing C[" << a << "," << b << "] = " << C[a][b] << endl; C[a][b] = -1; chosen.push_back({a,b}); chosen_starts[b].push_back(a); chosen_ends[a].push_back(b); }; auto eliminate = [&](int a, int b) { if(C[a][b] < 0) { // cerr << "Not eliminating C[" << a << "," << b << "] = " << C[a][b] << endl; return; } // cerr << "Eliminating C[" << a << "," << b << "] = " << C[a][b] << endl; C[a][b] = -2; eliminated.push_back({a,b}); chosen_starts[b].push_back(a); chosen_ends[a].push_back(b); }; vector<vector<bool>> V; V.resize(n); long long sum = 0; int count; count = 0; for(size_t i=0; count < n && i<best.size(); i++) { auto &b = best[i]; if(C[b.first][b.second] >= 0) { for(auto s: chosen_starts[b.second]) { // s = begin of an interval ending at the same point as ours if(s < b.first) { eliminate(s, b.first-1); } else if(s > b.first) { eliminate(b.first, s-1); } else { assert(0); // shouldn't happen, as this would mean that the interval was already chosen! } } for(auto s: chosen_starts[b.first-1]) { // s = begin of the interval ending just before ours eliminate(s, b.second); } for(auto s: chosen_ends[b.first]) { // s = end of an interval starting at the same point as ours if(s > b.second) { eliminate(b.second + 1, s); } else if(s < b.second) { eliminate(s + 1, b.second); } else { assert(0); // shouldn't happen, as this would mean that the interval was already chosen! } } for (auto s: chosen_ends[b.second+1]) { // s = end of an interval starting just after our ends eliminate(b.first, s); } vector<bool> R(n); for(int i=0; i<n; i++) { R[i] = b.first <= i && i <= b.second; } int first_1 = b.first; while(first_1 >= 0 && V[first_1].size() != 0) { assert(V[first_1][first_1]); int new_first_1 = -1; auto &S = V[first_1]; for(int i = first_1; i < n; i++) { R[i] = R[i] ^ S[i]; if(R[i] && new_first_1 == -1) { new_first_1 = i; } } first_1 = new_first_1; } if(first_1 >= 0) { assert(V[first_1].size() == 0); V[first_1] = R; sum += C[b.first][b.second]; choose(b.first, b.second); count++; } } } assert(count == n); cout << sum << endl; return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | #include <iostream> #include <vector> #include <deque> #include <map> #include <algorithm> #include <assert.h> using namespace std; typedef pair<short,short> interval; typedef deque<interval> intervals; int main() { ios_base::sync_with_stdio(false); int n; cin >> n; vector<vector<int> > C; C.resize(n); for(int i=0; i<n; i++) { C[i].resize(n); for(int j=i; j<n; j++) { cin >> C[i][j]; } } vector<interval> best; for(int i=0; i<n; i++) { for(int j=i; j<n; j++) { best.push_back({i,j}); } } sort(best.begin(), best.end(), [&C](const interval &a, const interval &b) -> bool { return C[a.first][a.second] < C[b.first][b.second]; } ); vector<interval> chosen, eliminated; map<int,vector<int>> chosen_ends, chosen_starts; auto choose = [&](int a, int b) { assert(C[a][b] >= 0); // cerr << "Choosing C[" << a << "," << b << "] = " << C[a][b] << endl; C[a][b] = -1; chosen.push_back({a,b}); chosen_starts[b].push_back(a); chosen_ends[a].push_back(b); }; auto eliminate = [&](int a, int b) { if(C[a][b] < 0) { // cerr << "Not eliminating C[" << a << "," << b << "] = " << C[a][b] << endl; return; } // cerr << "Eliminating C[" << a << "," << b << "] = " << C[a][b] << endl; C[a][b] = -2; eliminated.push_back({a,b}); chosen_starts[b].push_back(a); chosen_ends[a].push_back(b); }; vector<vector<bool>> V; V.resize(n); long long sum = 0; int count; count = 0; for(size_t i=0; count < n && i<best.size(); i++) { auto &b = best[i]; if(C[b.first][b.second] >= 0) { for(auto s: chosen_starts[b.second]) { // s = begin of an interval ending at the same point as ours if(s < b.first) { eliminate(s, b.first-1); } else if(s > b.first) { eliminate(b.first, s-1); } else { assert(0); // shouldn't happen, as this would mean that the interval was already chosen! } } for(auto s: chosen_starts[b.first-1]) { // s = begin of the interval ending just before ours eliminate(s, b.second); } for(auto s: chosen_ends[b.first]) { // s = end of an interval starting at the same point as ours if(s > b.second) { eliminate(b.second + 1, s); } else if(s < b.second) { eliminate(s + 1, b.second); } else { assert(0); // shouldn't happen, as this would mean that the interval was already chosen! } } for (auto s: chosen_ends[b.second+1]) { // s = end of an interval starting just after our ends eliminate(b.first, s); } vector<bool> R(n); for(int i=0; i<n; i++) { R[i] = b.first <= i && i <= b.second; } int first_1 = b.first; while(first_1 >= 0 && V[first_1].size() != 0) { assert(V[first_1][first_1]); int new_first_1 = -1; auto &S = V[first_1]; for(int i = first_1; i < n; i++) { R[i] = R[i] ^ S[i]; if(R[i] && new_first_1 == -1) { new_first_1 = i; } } first_1 = new_first_1; } if(first_1 >= 0) { assert(V[first_1].size() == 0); V[first_1] = R; sum += C[b.first][b.second]; choose(b.first, b.second); count++; } } } assert(count == n); cout << sum << endl; return 0; } |