Pro
https://acm.hdu.edu.cn/showproblem.php?pid=7172
Sol
先考虑没有w的限制的我不会的经典模型怎么做。
∵
∣
x
∣
=
m
a
x
(
x
,
−
x
)
\because |x|=max(x,-x)
∵∣x∣=max(x,−x)
∴
m
a
x
(
∣
x
′
−
x
i
∣
+
∣
y
′
−
y
i
∣
)
\therefore max({|x^{'}-x_i|+|y^{'}-y_i|})
∴max(∣x′−xi∣+∣y′−yi∣)
=
m
a
x
{
m
a
x
(
x
′
−
x
i
,
−
x
′
+
x
i
)
+
m
a
x
(
y
′
−
y
i
,
−
y
′
+
y
i
)
}
=max\{max(x^{'}-x_i, -x^{'}+x_i)+ {max(y^{'}-y_i, -y^{'}+y_i)}\}
=max{max(x′−xi,−x′+xi)+max(y′−yi,−y′+yi)}
=
m
a
x
{
x
′
−
x
i
+
y
′
−
y
i
,
x
′
−
x
i
−
y
′
+
y
i
,
−
x
′
+
x
i
+
y
′
−
y
i
,
−
x
′
+
x
i
−
y
′
+
y
i
}
=max\{x^{'}-x_i+y^{'}-y_i, x^{'}-x_i-y^{'}+y_i, -x^{'}+x_i+y^{'}-y_i,-x^{'}+x_i-y^{'}+y_i \}
=max{x′−xi+y′−yi,x′−xi−y′+yi,−x′+xi+y′−yi,−x′+xi−y′+yi}
=
m
a
x
{
(
x
′
+
y
′
)
+
(
−
x
i
−
y
i
)
,
(
x
′
−
y
′
)
+
(
−
x
i
+
y
i
)
,
(
−
x
′
+
y
′
)
+
(
x
i
−
y
i
)
,
(
−
x
′
−
y
′
)
+
(
x
i
+
y
i
)
}
=max\{(x^{'}+y^{'})+(-x_i-y_i), (x^{'}-y^{'})+(-x_i+y_i), (-x^{'}+y^{'})+(x_i-y_i),(-x^{'}-y^{'})+(x_i+y_i) \}
=max{(x′+y′)+(−xi−yi),(x′−y′)+(−xi+yi),(−x′+y′)+(xi−yi),(−x′−y′)+(xi+yi)}
因此只需要维护
−
x
i
−
y
i
,
−
x
i
+
y
i
,
x
i
−
y
i
,
x
i
+
y
i
-x_i-y_i,-x_i+y_i,x_i-y_i,x_i+y_i
−xi−yi,−xi+yi,xi−yi,xi+yi就可以
O
(
1
)
O(1)
O(1)的时间求出距离该点的曼哈顿距离最大值。
而本题加入w的限制后,有以下两种二分思路来做:(经过测试,第一种虽做法虽然只比第二种多了个log,但是因为此处的n比较大,因此不能通过;第二种方法关掉流同步的cin和快读也不能A掉,只能scanf才A掉哈哈哈,归为hdu机子的问题上次1e5的O(n)都给我T了我还记着呢)
主要是check(judge)函数的区别:
1、直接二分答案,比如想要判断答案是不是大于等于x,那么找到第一个权值大于等于x的点,根据上面的式子求出原始模型的距离,然后与x比较即可。
因为外面有一层二分,里面可以使用lower_bound二分得到点的下标,因此总的时间复杂度为 O ( n l o g n l o g n ) O(nlognlogn) O(nlognlogn)
2、二分城镇
考虑判断第x个城镇,它的点权为a[x].w,求出编号大于等于x的城镇中到询问点的最大曼哈顿距离d
如果d>a[x].w,答案一定大于等于a[x].w,因此需要进一步二分右半区间;反之同理。总的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
Code
1.二分答案:
//By cls1277
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define Fo(i,a,b) for(LL i=(a); i<=(b); i++)
#define Ro(i,b,a) for(LL i=(b); i>=(a); i--)
#define Eo(i,x,_) for(LL i=head[x]; i; i=_[i].next)
#define Ms(a,b) memset((a),(b),sizeof(a))
#define endl '\n'
const LL maxn = 1e5+5;
LL n, q;
struct Node {
LL x, y, w;
}a[maxn];
LL b[maxn];
inline LL read() {
LL x = 0, f = 1;char c = getchar();
while (!isdigit(c)) { if (c == '-')f = -f;c = getchar(); }
while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48ll), c = getchar();
return x * f;
}
LL f[4][maxn]; //0:x+y 1:x-y 2:-x+y 3:-x-y
bool operator < (const Node&x, const Node&y) {
return x.w<y.w;
}
bool judge(LL x, LL y, LL w) {
LL idx = lower_bound(b+1, b+n+1, w)-b;
LL d = max({x+y+f[3][idx], x-y+f[2][idx], -x+y+f[1][idx], -x-y+f[0][idx]});
return (d>=w);
}
int main() {
// ios::sync_with_stdio(false);
// cin.tie(nullptr);
#ifdef DEBUG
freopen("data.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
LL t; scanf("%lld",&t); //t=read(); //cin>>t;
while(t--) {
scanf("%lld%lld",&n,&q);
// n=read(); q=read(); //cin>>n>>q;
Fo(i,1,n) {
// a[i].x = read();
// a[i].y = read();
// a[i].w = read();
scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].w);
}
//cin>>a[i].x>>a[i].y>>a[i].w;
sort(a+1, a+n+1);
Fo(i,1,n) {
b[i] = a[i].w;
f[0][i] = f[1][i] = f[2][i] = f[3][i] = 0;
}
f[0][n] = a[n].x+a[n].y;
f[1][n] = a[n].x-a[n].y;
f[2][n] = -a[n].x+a[n].y;
f[3][n] = -a[n].x-a[n].y;
Ro(i,n-1,1) {
f[0][i] = max(f[0][i+1], a[i].x+a[i].y);
f[1][i] = max(f[1][i+1], a[i].x-a[i].y);
f[2][i] = max(f[2][i+1], -a[i].x+a[i].y);
f[3][i] = max(f[3][i+1], -a[i].x-a[i].y);
}
while(q--) {
LL _x, _y; scanf("%lld%lld", &_x, &_y); // _x=read(); _y=read(); //cin>>_x>>_y;
LL l=0, r=a[n].w;
while(l<r) {
LL mid=(l+r+1)>>1;
if(judge(_x, _y, mid)) l = mid;
else r = mid-1;
}
// cout<<l<<endl;
printf("%lld\n",l);
}
}
return 0;
}
2.二分城镇:
//By cls1277
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define Fo(i,a,b) for(LL i=(a); i<=(b); i++)
#define Ro(i,b,a) for(LL i=(b); i>=(a); i--)
#define Eo(i,x,_) for(LL i=head[x]; i; i=_[i].next)
#define Ms(a,b) memset((a),(b),sizeof(a))
#define endl '\n'
const LL maxn = 1e5+5;
LL n, q;
struct Node {
LL x, y, w;
}a[maxn];
LL b[maxn];
inline LL read() {
LL x = 0, f = 1;char c = getchar();
while (!isdigit(c)) { if (c == '-')f = -f;c = getchar(); }
while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48ll), c = getchar();
return x * f;
}
LL f[4][maxn]; //0:x+y 1:x-y 2:-x+y 3:-x-y
bool operator < (const Node&x, const Node&y) {
return x.w<y.w;
}
LL ans = 0;
bool judge(LL x, LL y, LL idx) {
LL d = max({x+y+f[3][idx], x-y+f[2][idx], -x+y+f[1][idx], -x-y+f[0][idx]});
if(d>=a[idx].w) {
ans = max(ans, a[idx].w);
return true;
} else {
ans = max(ans, d);
return false;
}
}
int main() {
// ios::sync_with_stdio(false);
// cin.tie(nullptr);
#ifdef DEBUG
freopen("data.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
LL t; scanf("%lld",&t); //t=read(); //cin>>t;
while(t--) {
scanf("%lld%lld",&n,&q);
// n=read(); q=read(); //cin>>n>>q;
Fo(i,1,n) {
// a[i].x = read();
// a[i].y = read();
// a[i].w = read();
scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].w);
}
//cin>>a[i].x>>a[i].y>>a[i].w;
sort(a+1, a+n+1);
Fo(i,1,n) {
b[i] = a[i].w;
f[0][i] = f[1][i] = f[2][i] = f[3][i] = 0;
}
f[0][n] = a[n].x+a[n].y;
f[1][n] = a[n].x-a[n].y;
f[2][n] = -a[n].x+a[n].y;
f[3][n] = -a[n].x-a[n].y;
Ro(i,n-1,1) {
f[0][i] = max(f[0][i+1], a[i].x+a[i].y);
f[1][i] = max(f[1][i+1], a[i].x-a[i].y);
f[2][i] = max(f[2][i+1], -a[i].x+a[i].y);
f[3][i] = max(f[3][i+1], -a[i].x-a[i].y);
}
while(q--) {
LL _x, _y; scanf("%lld%lld", &_x, &_y); // _x=read(); _y=read(); //cin>>_x>>_y;
LL l=0, r=n;
ans = 0;
while(l<r) {
LL mid=(l+r+1)>>1;
if(judge(_x, _y, mid)) l = mid;
else r = mid-1;
}
// cout<<l<<endl;
printf("%lld\n",ans);
}
}
return 0;
}