链接:https://ac.nowcoder.com/acm/problem/221163
来源:牛客网
示例1
输入
复制
2 3
0 5
5 0
0 1
0 3
3 0
输出
复制
0 0
3
示例2
输入
复制
6 5
-6 0
-4 0
-3 0
-4 -2
-3 -2
-2 -3
-6 -1
-4 -1
-3 -1
-5 -3
0 -3
输出
复制
-6 -3
3
示例3
输入
复制
1 2
0 0
1 0
0 1
输出
复制
0 0
2
upd:这题没数据QAQ所以下面代码只过了样例
大意就是给一些church和一些monument的坐标,一个church是mighty的当且仅当起所在的行有两个以上的monument/列有两个以上的monument。现在可以在任何地方(包括已经有monument或者church的位置)选择一处建一个monument,问在哪里建可以使新增加的mighty church最多。
首先看到坐标范围要离散化,然后直接暴力模拟即可。先找出每行每列的unmighty church的数量(通过每行/每列的church数量减去每行/每列的mighty church数量)以及求出离散化后每个church是否为unmighty church,然后遍历所有可能的选点坐标更新最大值即可。
注意特判m或者c为0的情况,不然会收获无数个段错误
看别人写的发现好多都用了unordered_map,我是废物
#include <bits/stdc++.h>
#define MAX 40005//随便开的大一点
using namespace std;
int m, c;
struct monument {
int x, y;
} mon[1005];
struct church {
int x, y;
} chu[1005];
vector<int> v, monpos;
//以下的位置都是离散化后的位置
int hmx[MAX], hmy[MAX];//hmx[i]这一行monument的数量
int cx[MAX], cy[MAX];//cx[i]代表i这一行的church的数量
int cmx[MAX], cmy[MAX];//cmx[i]代表i这一行的mighty church的数量
int umcx[MAX];//ucmx[i]代表i这一行的un mighty church的数量
int umcy[MAX];
bool umcxy[MAX][MAX];//标记x,y是否为un mighty church
int px, py, maxx = 0;
bool check(int id) {
if(hmx[chu[id].x] >= 2 || hmy[chu[id].y] >= 2) return 1;
return 0;
}
int main() {
cin >> m >> c;
for(int i = 1; i <= m; i++){
int x, y;
cin >> x >> y;
v.push_back(x);
v.push_back(y);
mon[i].x = x;
mon[i].y = y;
monpos.push_back(x);//每个monument涉及的行
monpos.push_back(y);
}
for(int i = 1; i <= c; i++){
int x, y;
cin >> x >> y;
v.push_back(x);
v.push_back(y);
chu[i].x = x;
chu[i].y = y;
}
if(m == 0 || c == 0) {
cout << 0 << " " << 0 << endl;
cout << 0;
return 0;
}
sort(v.begin(), v.end());
vector<int>::iterator it = unique(v.begin(), v.end());
v.erase(it, v.end());
sort(monpos.begin(), monpos.end());
vector<int>::iterator it1 = unique(monpos.begin(), monpos.end());
monpos.erase(it1, monpos.end());
for(int i = 0; i < monpos.size(); i++) {
monpos[i] = lower_bound(v.begin(), v.end(), monpos[i]) - v.begin();
}
for(int i = 1; i <= m; i++){
mon[i].x = lower_bound(v.begin(), v.end(), mon[i].x) - v.begin();
mon[i].y = lower_bound(v.begin(), v.end(), mon[i].y) - v.begin();
hmx[mon[i].x]++;
hmy[mon[i].y]++;
}
for(int i = 1; i <= c; i++){
chu[i].x = lower_bound(v.begin(), v.end(), chu[i].x) - v.begin();
chu[i].y = lower_bound(v.begin(), v.end(), chu[i].y) - v.begin();
cx[chu[i].x]++;
cy[chu[i].y]++;
}
//现在要求umcx, umcy这两个数组
//不妨先求出来cmx, cmy
for(int i = 1; i <= c; i++) {
if(check(i)) {//判断它所在的行 / 列的monument的数量是否大于等于2
cmx[chu[i].x]++;
cmy[chu[i].y]++;
}
}
for(int i = 0; i <= 4000; i++) {
umcx[i] = cx[i] - cmx[i];
umcy[i] = cy[i] - cmy[i];
}
for(int i = 1; i <= c; i++) {
if(!check(i)) umcxy[chu[i].x][chu[i].y] = 1;
}
for(int i = 0; i < monpos.size(); i++) {//建造位置只可能选在所在行/列有monument的位置
for(int j = 0; j < monpos.size(); j++) {
int x = monpos[i], y = monpos[j];//遍历位置
int tmp = 0;
if(hmx[x]) {
tmp += umcx[x];//这个位置建造monument后这一行增加的mighty church数量
}
if(hmy[y]) {
tmp += umcy[y];
}
if(umcxy[x][y]) tmp--;//减去重复加的
if(tmp > maxx) {
maxx = tmp;
px = x, py = y;
}
}
}
px = v[px], py = v[py];
cout << px << " " << py << endl;
cout << maxx;
return 0;
}