P3540 [POI2012]SQU-Squarks
*P3540 [POI2012]SQU-Squarks
POI 合集。
将给出的
先考虑已知一些数时,如何推出剩下来的数:假设
因此,我们断言如果确定 map 打标记产生(代码用了 priority_queue)。特别的,若求出的
接下来考虑如何求
综上,时间复杂度三方对数。由于大部分下标很快无解,因此常数非常小。
const int N = 300 + 5;
int n, m, a[N * N >> 1];
uint mp[N * N * 35];
void s(int x) {mp[x >> 5] |= 1u << (x & 31);}
bool query(int x) {return mp[x >> 5] >> (x & 31) & 1;}
vector <vint> ans;
int main(){
cin >> n, m = n * (n - 1) >> 1;
for(int i = 1; i <= m; i++) a[i] = read(), s(a[i]);
sort(a + 1, a + m + 1), reverse(a + 1, a + m + 1);
for(int i = 3; i <= n; i++) if(i == 3 || a[i] != a[i - 1]) {
static int x[N], sum; sum = a[1] + a[2] + a[i];
if(sum & 1) continue; x[1] = (sum >> 1) - a[i];
if(x[1] < n) continue;
priority_queue <int> q; bool ok = 1;
for(int j = 2, p = 1; j <= n && ok; j++) {
while(!q.empty() && q.top() == a[p]) q.pop(), p++;
x[j] = a[p] - x[1];
if(x[j] >= x[j - 1] || x[j] < 0) ok = 0;
for(int k = 1; k < j && ok; k++) ok &= query(x[k] + x[j]), q.push(x[k] + x[j]);
} if(ok) {vint p; for(int j = n; j; j--) p.pb(x[j]); ans.pb(p);}
}
cout << ans.size() << endl, rev(ans);
for(vint it : ans) {for(int p : it) cout << p << " "; cout << endl;}
return flush(), 0;
}