/* 2014 * Maciej Szeptuch * II UWr */ #include <cstdio> #include <algorithm> using namespace std; class iTree { static const int SIZE = 2048; int data[SIZE * 2]; public: iTree(void); void insert(int v); int count(int start, int end, int iStart = 0, int iEnd = SIZE - 1, int pos = 1); }; // class iTree int cups, cost[2048][2048], sortme[2048 * 2048]; bool full[2048][2048]; long long result; iTree tree[2048]; bool compareCost(int a, int b); bool check(int h, int w); void use(int h, int w); void mark(int h, int w); int main(void) { scanf("%d", &cups); for(int h = 0, s = 0; h < cups; ++ h) for(int w = 0; w < cups - h; ++ w, ++ s) { scanf("%d", &cost[h][w]); sortme[s] = h * cups + w; } sort(sortme, sortme + cups * (cups + 1) / 2, compareCost); for(int c = 0, r = 0, _ = cups * (cups + 1) / 2; c < _ && r < cups; ++ c) if(check(sortme[c] / cups, sortme[c] % cups)) { //printf("got %d %d for %d\n", sortme[c] / cups, sortme[c] % cups, cost[sortme[c] / cups][sortme[c] % cups]); use(sortme[c] / cups, sortme[c] % cups); result += cost[sortme[c] / cups][sortme[c] % cups]; ++ r; } printf("%lld\n", result); return 0; } inline bool compareCost(int a, int b) { return cost[a / cups][a % cups] < cost[b / cups][b % cups]; } inline bool check(int h, int w) { if(full[h][w]) return false; int cnt = 0; for(int l = 0; l <= h; ++ l) cnt += tree[h - l].count(w, w + l); //printf("%d %d => %d\n", h, w, cnt); if(cnt > h) return false; if(cnt == h) { //printf("FULL %d %d\n", h, w); mark(h, w); } return true; } inline void use(int h, int w) { tree[h].insert(w); } inline void mark(int h, int w) { full[h][w] = true; if(!h) return; -- h; if(!full[h][w]) mark(h, w); if(!full[h][w + 1]) mark(h, w + 1); } inline iTree::iTree(void) :data() { } inline void iTree::insert(int v) { v += SIZE; while(v > 0) { ++ data[v]; v /= 2; } } inline int iTree::count(int start, int end, int iStart/* = 0*/, int iEnd/* = SIZE - 1*/, int pos/* = 1*/) { if(iStart == start && end == iEnd) return data[pos]; int iMid = (iStart + iEnd) / 2; if(end <= iMid) return count(start, end, iStart, iMid, pos * 2); if(start > iMid) return count(start, end, iMid + 1, iEnd, pos * 2 + 1); return count(start, iMid, iStart, iMid, pos * 2) + count(iMid + 1, end, iMid + 1, iEnd, pos * 2 + 1); }
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 | /* 2014 * Maciej Szeptuch * II UWr */ #include <cstdio> #include <algorithm> using namespace std; class iTree { static const int SIZE = 2048; int data[SIZE * 2]; public: iTree(void); void insert(int v); int count(int start, int end, int iStart = 0, int iEnd = SIZE - 1, int pos = 1); }; // class iTree int cups, cost[2048][2048], sortme[2048 * 2048]; bool full[2048][2048]; long long result; iTree tree[2048]; bool compareCost(int a, int b); bool check(int h, int w); void use(int h, int w); void mark(int h, int w); int main(void) { scanf("%d", &cups); for(int h = 0, s = 0; h < cups; ++ h) for(int w = 0; w < cups - h; ++ w, ++ s) { scanf("%d", &cost[h][w]); sortme[s] = h * cups + w; } sort(sortme, sortme + cups * (cups + 1) / 2, compareCost); for(int c = 0, r = 0, _ = cups * (cups + 1) / 2; c < _ && r < cups; ++ c) if(check(sortme[c] / cups, sortme[c] % cups)) { //printf("got %d %d for %d\n", sortme[c] / cups, sortme[c] % cups, cost[sortme[c] / cups][sortme[c] % cups]); use(sortme[c] / cups, sortme[c] % cups); result += cost[sortme[c] / cups][sortme[c] % cups]; ++ r; } printf("%lld\n", result); return 0; } inline bool compareCost(int a, int b) { return cost[a / cups][a % cups] < cost[b / cups][b % cups]; } inline bool check(int h, int w) { if(full[h][w]) return false; int cnt = 0; for(int l = 0; l <= h; ++ l) cnt += tree[h - l].count(w, w + l); //printf("%d %d => %d\n", h, w, cnt); if(cnt > h) return false; if(cnt == h) { //printf("FULL %d %d\n", h, w); mark(h, w); } return true; } inline void use(int h, int w) { tree[h].insert(w); } inline void mark(int h, int w) { full[h][w] = true; if(!h) return; -- h; if(!full[h][w]) mark(h, w); if(!full[h][w + 1]) mark(h, w + 1); } inline iTree::iTree(void) :data() { } inline void iTree::insert(int v) { v += SIZE; while(v > 0) { ++ data[v]; v /= 2; } } inline int iTree::count(int start, int end, int iStart/* = 0*/, int iEnd/* = SIZE - 1*/, int pos/* = 1*/) { if(iStart == start && end == iEnd) return data[pos]; int iMid = (iStart + iEnd) / 2; if(end <= iMid) return count(start, end, iStart, iMid, pos * 2); if(start > iMid) return count(start, end, iMid + 1, iEnd, pos * 2 + 1); return count(start, iMid, iStart, iMid, pos * 2) + count(iMid + 1, end, iMid + 1, iEnd, pos * 2 + 1); } |