CF1419F Rain of Fire

显然这题答案具有单调性,现在我们考虑给定一个$T$怎么check

首先我们可以把所有不通过新点就可以互达的点合并成一个联通块。

容易发现当联通块个数$=1$时肯定有解,$>4$时无解,剩下情况我们进行分类讨论

1. 有两个联通块

如果我们能找到两个点位于不同的联通块,并且他们在一条直线上且曼哈顿距离<=2T 或 两点的x,y坐标绝对值之差均小于T则有解

2. 有三个联通块

首先我们把所有在一条直线上相邻并且不属于一个联通块的点对(a, b)处理出来,对于每个点对可以找到点c与这两个点所属联通块都不同,若c到直线距离,a、b到c在线段上的投影距离均小于T,则合法

3. 有四个联通块

将找点c换成找点对(c,d)满足线段(a,b),(c,d)垂直,且a,b,c,d分属四个不同的联通块,接下来做法与3个联通块类似

时间复杂度O($n^2\log_2{2\times 10^9}$)

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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <bits/stdc++.h>

#define R register
#define ll long long
#define pir std::pair<ll, ll>
#define mp(i, j) std::make_pair(i, j)
#define sum(a, b, mod) (((a) + (b)) % mod)
#define It std::map<ll, std::vector<ll>>::iterator

const ll MaxN = 1e3 + 10;

ll n, x[MaxN], y[MaxN], f[MaxN];
std::unordered_map<ll, ll> trash;
std::map<ll, std::vector<ll>> lx, ly;
std::vector<std::pair<ll, ll>> X, Y, line;

ll Abs(ll x) { return (x < 0) ? (-x) : x; }
ll cmpx(ll a, ll b) { return x[a] < x[b]; }
ll cmpy(ll a, ll b) { return y[a] < y[b]; }

ll getf(ll x)
{
if (x != f[x])
f[x] = getf(f[x]);
return f[x];
}

void merge(ll x, ll y)
{
ll fx = getf(x), fy = getf(y);
if (fx != fy) f[fx] = fy;
}

inline ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while (ch > '9' || ch < '0')
{
if (ch == '-')
f = 0;
ch = getchar();
}
while (ch <= '9' && ch >= '0')
x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return f ? x : (-x);
}

ll check(ll mid)
{
trash.clear();
for (ll i = 1; i <= n; i++)
f[i] = i;
for (It it = lx.begin(); it != lx.end(); it++)
{
std::vector<ll> &v = it->second;
for (ll i = 1; i < v.size(); i++)
if (Abs(y[v[i]] - y[v[i - 1]]) <= mid)
merge(v[i], v[i - 1]);
}
for (It it = ly.begin(); it != ly.end(); it++)
{
std::vector<ll> &v = it->second;
for (ll i = 1; i < v.size(); i++)
if (Abs(x[v[i]] - x[v[i - 1]]) <= mid)
merge(v[i], v[i - 1]);
}
ll siz = 0;
for (ll i = 1; i <= n; i++)
// getf(i), printf("%lld ", f[i]),
siz += (trash[getf(i)] == 0), trash[getf(i)] = 1;
// printf("# %lld %lld\n", mid, siz);
if (siz == 1)
return 1;
else if (siz == 2)
{
for (ll i = 1; i <= n; i++)
for (ll j = i + 1; j <= n; j++)
if (f[i] != f[j])
{
if (Abs(x[i] - x[j]) == 0 && Abs(y[i] - y[j]) <= 2 * mid)
return 1;
if (Abs(y[i] - y[j]) == 0 && Abs(x[i] - x[j]) <= 2 * mid)
return 1;
if (Abs(x[i] - x[j]) <= mid && Abs(y[i] - y[j]) <= mid)
return 1;
}
}
else if (siz == 3)
{
line.clear();
for (It it = lx.begin(); it != lx.end(); it++)
{
std::vector<ll> &v = it->second;
for (ll i = 1; i < v.size(); i++)
if (f[v[i]] != f[v[i - 1]])
line.push_back(mp(v[i], v[i - 1]));
}
for (It it = ly.begin(); it != ly.end(); it++)
{
std::vector<ll> &v = it->second;
for (ll i = 1; i < v.size(); i++)
if (f[v[i]] != f[v[i - 1]])
line.push_back(mp(v[i], v[i - 1]));
}
for (auto li : line)
{
ll l = li.first, r = li.second;
for (ll i = 1; i <= n; i++)
{
if (f[l] != f[i] && f[i] != f[r])
{
if (x[l] == x[r])
{
if (Abs(y[l] - y[i]) <= mid && Abs(y[r] - y[i]) <= mid)
if (Abs(x[l] - x[i]) <= mid)
return 1;
}
else if (Abs(x[l] - x[i]) <= mid && Abs(x[r] - x[i]) <= mid)
if (Abs(y[l] - y[i]) <= mid)
return 1;
}
}
}
}
else if (siz == 4)
{
X.clear(), Y.clear();
for (It it = lx.begin(); it != lx.end(); it++)
{
std::vector<ll> &v = it->second;
for (ll i = 1; i < v.size(); i++)
if (f[v[i]] != f[v[i - 1]])
X.push_back(mp(v[i], v[i - 1]));
}
for (It it = ly.begin(); it != ly.end(); it++)
{
std::vector<ll> &v = it->second;
for (ll i = 1; i < v.size(); i++)
if (f[v[i]] != f[v[i - 1]])
Y.push_back(mp(v[i], v[i - 1]));
}
for (auto x1 : X)
{
for (auto y1 : Y)
{
ll a = x1.first, b = x1.second;
ll c = y1.first, d = y1.second;
if (f[a] != f[c] && f[a] != f[d])
if (f[b] != f[c] && f[b] != f[d])
if (Abs(x[a] - x[c]) <= mid && Abs(x[a] - x[d]) <= mid)
if (Abs(y[c] - y[a]) <= mid && Abs(y[c] - y[b]) <= mid)
return 1;
}
}
}
return 0;
}

signed main()
{
n = read();
for (ll i = 1; i <= n; i++)
{
x[i] = read(), y[i] = read();
lx[x[i]].push_back(i);
ly[y[i]].push_back(i);
}
for (It it = lx.begin(); it != lx.end(); it++)
{
std::vector<ll> &v = it->second;
std::sort(v.begin(), v.end(), cmpy);
}
for (It it = ly.begin(); it != ly.end(); it++)
{
std::vector<ll> &v = it->second;
std::sort(v.begin(), v.end(), cmpx);
}
ll l = 1, r = 0x7f7f7f7f;
while (l < r)
{
ll mid = (l + r) >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
if (l == 0x7f7f7f7f)
l = -1;
printf("%lld\n", l);
return 0;
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×