#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; } |
English