結果
| 問題 |
No.2884 Pieces on Squares
|
| コンテスト | |
| ユーザー |
pockyny
|
| 提出日時 | 2024-09-14 17:03:32 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 114 ms / 2,000 ms |
| コード長 | 3,447 bytes |
| コンパイル時間 | 993 ms |
| コンパイル使用メモリ | 89,456 KB |
| 最終ジャッジ日時 | 2025-02-24 08:36:40 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge6 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 45 |
ソースコード
#include <iostream>
#include <vector>
using namespace std;
struct UF{
vector<int> par,sz;
vector<vector<int>> mergeTree;
UF(int n, bool useMergeTree = false){
sz.resize(n); par.resize(n);
for(int i=0;i<n;i++) sz[i] = 1, par[i] = i;
if(useMergeTree){
sz.resize(2*n); par.resize(2*n);
for(int i=n;i<2*n;i++) sz[i] = 1, par[i] = i;
mergeTree.resize(2*n);
}
}
int find(int x){
if(par[x]==x) return x;
return par[x] = find(par[x]);
}
void unite(int x,int y){
x = find(x); y = find(y);
if(x==y) return;
if(sz[x]>sz[y]) swap(x,y);
sz[y] += sz[x];
par[x] = y;
}
bool same(int x,int y){return find(x)==find(y);}
void merge(int child,int parent){
//parentが親,merge過程を表す木などで使用
child = find(child); parent = find(parent);
if(child==parent) return;
mergeTree[parent].push_back(child);
sz[parent] += sz[child];
par[child] = parent;
}
};
#include <iostream>
#include <vector>
#include <set>
typedef long long ll;
using namespace std;
vector<int> H[5010],W[5010];
ll dp_mn[5010],dp_mx[5010],ndp_mn[5010],ndp_mx[5010],inf = 1000000000;
int a[200010],b[200010];
int main(){
int i,j,h,w,n; cin >> h >> w >> n;
UF ufh(h),ufw(w);
for(i=0;i<n;i++){
cin >> a[i] >> b[i]; a[i]--; b[i]--;
H[a[i]].push_back(b[i]); W[b[i]].push_back(a[i]);
}
for(i=0;i<h;i++){
for(j=1;j<H[i].size();j++) ufw.unite(H[i][j],H[i][0]);
}
for(i=0;i<w;i++){
for(j=1;j<W[i].size();j++) ufh.unite(W[i][j],W[i][0]);
}
set<pair<int,int>> s;
for(i=0;i<n;i++){
s.insert({ufh.find(a[i]),ufw.find(b[i])});
}
for(i=0;i<=h;i++) dp_mx[i] = ndp_mx[i] = -inf, dp_mn[i] = ndp_mn[i] = inf;
dp_mn[0] = dp_mx[0] = 0;
// 黒 := h_c*w+ w_c*h - 2*h_c*w_c = h_c*w + (h - h_c*2)*w_c, (wの最小,最大を持てばOK)
int _h = h,_w = w;
for(auto [p,q]:s){
int h_c = ufh.sz[p],w_c = ufw.sz[q];
_h -= h_c; _w -= w_c;
// cout << "s := " << h_c << " " << w_c << endl;
for(i=0;i<=h;i++){
if(i>=h_c){
ndp_mx[i] = max(ndp_mx[i],dp_mx[i - h_c] + w_c);
ndp_mn[i] = min(ndp_mn[i],dp_mn[i - h_c] + w_c);
}
ndp_mx[i] = max(ndp_mx[i],dp_mx[i]);
ndp_mn[i] = min(ndp_mn[i],dp_mn[i]);
}
for(i=0;i<=h;i++){
dp_mx[i] = ndp_mx[i]; ndp_mx[i] = -inf;
dp_mn[i] = ndp_mn[i]; ndp_mn[i] = inf;
}
}
ll ans = 0;
for(i=0;i<=h;i++){
for(j=0;j<=_h;j++){
// cout << i << " " << dp_mn[i] << " " << dp_mx[i] << "\n";
if(dp_mn[i]<=w) ans = max(ans,(i + j)*w + dp_mn[i]*h - dp_mn[i]*(i + j)*2);
if(dp_mx[i]>=0) ans = max(ans,(i + j)*w + (dp_mx[i] + _w)*h - (dp_mx[i] + _w)*(i + j)*2);
}
}
cout << ans << "\n";
// for(i=0;i<(1<<h);i++){
// for(j=0;j<(1<<w);j++){
// for(int k=0;k<n;k++){
// if((i>>a[k]&1)!=(j>>b[k]&1)) break;
// if(k==n - 1){
// int len_i = __builtin_popcount(i);
// int len_j = __builtin_popcount(j);
// cout << "ok " << i << " " << j << " " << len_i << " " << len_j << endl;
// }
// }
// }
// }
}
pockyny