#include <iostream> #include <algorithm> #include <vector> #include <stack> using namespace std; #define LL long long #define MAX_N 2010 #define INF 4001000000 int n; pair<pair<LL, LL>, int> P[MAX_N]; pair<LL, LL> origin0; pair<LL, LL> origin1; LL S[MAX_N]; LL R[MAX_N]; vector<int> B; vector<int> B1; pair<LL, LL> bounds; void clear() { B.clear(); B1.clear(); } LL maxSquare(int i) { LL ret = INF; for(int a = 0; a < n; ++a) { if(a != i) { if((P[a].first.first + S[a] > P[i].first.first && P[a].first.second > P[i].first.second) || (P[a].first.second + S[a] > P[i].first.second && P[a].first.first > P[i].first.first)) { ret = min(ret, max(P[a].first.second - P[i].first.second, P[a].first.first - P[i].first.first)); } } } return ret; } pair<LL, LL> knownBounds() { LL right = 0, top = 0; for(int i : B1) { right = max(right, P[i].first.first + S[i]); top = max(top, P[i].first.second + S[i]); } if(right == P[B.back()].first.first) right = INF; if(top == P[B.front()].first.second) top = INF; return {right, top}; } pair<bool, pair<LL, LL>> checkBCompletion(LL firstSize) { stack<pair<LL, LL>> stack; if(bounds.second != INF && bounds.second != P[B.front()].first.second + firstSize) { return {0, {0, 0}}; } stack.push({INF, P[B.front()].first.second + firstSize}); LL last = INF; for(int a = 0; a < int(B.size()); ++a) { auto p = P[B[a]].first; while(p.first >= stack.top().first) { if(p.first > stack.top().first) { return {0, {0, 0}}; } stack.pop(); } auto s = stack.top(); LL d = s.second - p.second; if(p.first + d > s.first) { return {0, {0, 0}}; } stack.push({p.first + d, p.second}); last = p.first + d; S[B[a]] = d; } while(stack.size() > 1) { if(last != stack.top().first) { return {0, {0, 0}}; } stack.pop(); } if(bounds.first != INF && bounds.first != last) { return {0, {0, 0}}; } return {1, {last, P[B.front()].first.second + firstSize}}; } bool checkRectangle(LL right, LL top) { LL area = (right - origin0.first) * (top - origin0.second); LL sum = 0; for(int a = 0; a < n; ++a) { sum += S[a] * S[a]; } return area == sum; } int main() { ios::sync_with_stdio(0); int tests; cin >> tests; while(tests--) { clear(); cin >> n; LL left = INF, bottom = INF; for(int a = 0; a < n; ++a) { cin >> P[a].first.first >> P[a].first.second; P[a].second = a; left = min(left, P[a].first.first); bottom = min(bottom, P[a].first.second); S[a] = 1; } if(n == 1) { cout << "TAK 1\n"; continue; } sort(P, P + n, [](const pair<pair<LL, LL>, int>& p1, const pair<pair<LL, LL>, int>& p2) { return make_pair(p1.first.second, p1.first.first) < make_pair(p2.first.second, p2.first.first); }); origin0 = P[0].first; if(origin0.first != left || origin0.second != bottom) { cout << "NIE\n"; continue; } for(int a = 0; a < n; ++a) { S[a] = maxSquare(a); if(S[a] == INF) { S[a] = 1; } } for(int a = 0; a < n; ++a) { S[a] = maxSquare(a); if(S[a] == INF) { S[a] = 1; B.push_back(a); } else { B1.push_back(a); } } std::reverse(B.begin(), B.end()); std::reverse(B1.begin(), B1.end()); origin1 = {P[B.front()].first.first, P[B.back()].first.second}; bounds = knownBounds(); bool isAnswer = 0; for(int a = 0; a <= int(B.size()); ++a) { LL firstSize; if(a == 0) firstSize = 1; else if(a < int(B.size())) firstSize = P[B[a]].first.first - origin1.first; else firstSize = P[B.back()].first.first - origin1.first + P[B.front()].first.second - origin1.second; auto r = checkBCompletion(firstSize); if(r.first) { if(checkRectangle(r.second.first, r.second.second)) { for(int i = 0; i < n; ++i) { R[P[i].second] = S[i]; } cout << "TAK "; for(int i = 0; i < n; ++i) { cout << R[i] << " "; } cout << "\n"; isAnswer = 1; } break; } } if(!isAnswer) { cout << "NIE\n"; } } 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 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | #include <iostream> #include <algorithm> #include <vector> #include <stack> using namespace std; #define LL long long #define MAX_N 2010 #define INF 4001000000 int n; pair<pair<LL, LL>, int> P[MAX_N]; pair<LL, LL> origin0; pair<LL, LL> origin1; LL S[MAX_N]; LL R[MAX_N]; vector<int> B; vector<int> B1; pair<LL, LL> bounds; void clear() { B.clear(); B1.clear(); } LL maxSquare(int i) { LL ret = INF; for(int a = 0; a < n; ++a) { if(a != i) { if((P[a].first.first + S[a] > P[i].first.first && P[a].first.second > P[i].first.second) || (P[a].first.second + S[a] > P[i].first.second && P[a].first.first > P[i].first.first)) { ret = min(ret, max(P[a].first.second - P[i].first.second, P[a].first.first - P[i].first.first)); } } } return ret; } pair<LL, LL> knownBounds() { LL right = 0, top = 0; for(int i : B1) { right = max(right, P[i].first.first + S[i]); top = max(top, P[i].first.second + S[i]); } if(right == P[B.back()].first.first) right = INF; if(top == P[B.front()].first.second) top = INF; return {right, top}; } pair<bool, pair<LL, LL>> checkBCompletion(LL firstSize) { stack<pair<LL, LL>> stack; if(bounds.second != INF && bounds.second != P[B.front()].first.second + firstSize) { return {0, {0, 0}}; } stack.push({INF, P[B.front()].first.second + firstSize}); LL last = INF; for(int a = 0; a < int(B.size()); ++a) { auto p = P[B[a]].first; while(p.first >= stack.top().first) { if(p.first > stack.top().first) { return {0, {0, 0}}; } stack.pop(); } auto s = stack.top(); LL d = s.second - p.second; if(p.first + d > s.first) { return {0, {0, 0}}; } stack.push({p.first + d, p.second}); last = p.first + d; S[B[a]] = d; } while(stack.size() > 1) { if(last != stack.top().first) { return {0, {0, 0}}; } stack.pop(); } if(bounds.first != INF && bounds.first != last) { return {0, {0, 0}}; } return {1, {last, P[B.front()].first.second + firstSize}}; } bool checkRectangle(LL right, LL top) { LL area = (right - origin0.first) * (top - origin0.second); LL sum = 0; for(int a = 0; a < n; ++a) { sum += S[a] * S[a]; } return area == sum; } int main() { ios::sync_with_stdio(0); int tests; cin >> tests; while(tests--) { clear(); cin >> n; LL left = INF, bottom = INF; for(int a = 0; a < n; ++a) { cin >> P[a].first.first >> P[a].first.second; P[a].second = a; left = min(left, P[a].first.first); bottom = min(bottom, P[a].first.second); S[a] = 1; } if(n == 1) { cout << "TAK 1\n"; continue; } sort(P, P + n, [](const pair<pair<LL, LL>, int>& p1, const pair<pair<LL, LL>, int>& p2) { return make_pair(p1.first.second, p1.first.first) < make_pair(p2.first.second, p2.first.first); }); origin0 = P[0].first; if(origin0.first != left || origin0.second != bottom) { cout << "NIE\n"; continue; } for(int a = 0; a < n; ++a) { S[a] = maxSquare(a); if(S[a] == INF) { S[a] = 1; } } for(int a = 0; a < n; ++a) { S[a] = maxSquare(a); if(S[a] == INF) { S[a] = 1; B.push_back(a); } else { B1.push_back(a); } } std::reverse(B.begin(), B.end()); std::reverse(B1.begin(), B1.end()); origin1 = {P[B.front()].first.first, P[B.back()].first.second}; bounds = knownBounds(); bool isAnswer = 0; for(int a = 0; a <= int(B.size()); ++a) { LL firstSize; if(a == 0) firstSize = 1; else if(a < int(B.size())) firstSize = P[B[a]].first.first - origin1.first; else firstSize = P[B.back()].first.first - origin1.first + P[B.front()].first.second - origin1.second; auto r = checkBCompletion(firstSize); if(r.first) { if(checkRectangle(r.second.first, r.second.second)) { for(int i = 0; i < n; ++i) { R[P[i].second] = S[i]; } cout << "TAK "; for(int i = 0; i < n; ++i) { cout << R[i] << " "; } cout << "\n"; isAnswer = 1; } break; } } if(!isAnswer) { cout << "NIE\n"; } } return 0; } |