题面:
题意:
在一个二维平面上,有许多点,其坐标为
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi) ,它们会沿
y
y
y 轴的负方向运动,你有两块长度为
k
k
k 且平行于
x
x
x 轴的的板子去save它们,问最多能save多少个点。(大概就是这么个意思)
思路:
有个憨憨想法:
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1] 表示第一块板子右端与直线x=i对齐,能save的点的个数
d
p
[
i
]
[
2
]
dp[i][2]
dp[i][2] 表示第二块板子右端与直线x=i对齐,能save的点的个数
d
p
[
i
]
[
2
]
=
m
a
x
j
<
=
i
−
k
d
p
[
j
]
[
1
]
+
d
p
[
i
]
[
1
]
dp[i][2] = max_{j <= i - k}dp[j][1] + dp[i][1]
dp[i][2]=maxj<=i−kdp[j][1]+dp[i][1]
二分 + 离散化 + 递推???瞎搞过的
#include<bits/stdc++.h>
#define ll long long
#define ms(x,a) memset(x,a,sizeof(x))
#define inf 0x3f3f3f3f
#define db double
using namespace std;
const int maxn = 2e5 + 10;
int x[maxn],mx[maxn],dp[maxn][3],tnt[maxn];
map<int,int>mp;
int main() {
int t;
scanf("%d",&t);
for(int ca = 1;ca <= t; ++ca){
int n,k;
scanf("%d%d",&n,&k);
mp.clear();
for(int i = 1;i <= n; ++i){
scanf("%d",&x[i]);
mp[x[i]]++;
dp[i][1] = dp[i][2] = mx[i] = 0;
}
for(int i = 1;i <= n; ++i){
int y;
scanf("%d",&y);
}
map<int,int>::iterator it;
n = 0;
for(it = mp.begin();it != mp.end(); ++it){
x[++n] = it->first;
}
tnt[0] = 0;
for(int i = 1;i <= n; ++i){
tnt[i] = tnt[i - 1] + mp[x[i]];
int pos = lower_bound(x + 1,x + 1 + i,x[i] - k) - x;
dp[i][1] = tnt[i] - tnt[pos - 1];
mx[i] = max(mx[i - 1],dp[i][1]);
}
int ans = 0;
for(int i = 1;i <= n; ++i){
int pos = lower_bound(x + 1,x + 1 + i,x[i] - k) - x;
dp[i][2] = mx[pos - 1] + dp[i][1];
ans = max(ans,dp[i][2]);
}
cout<<ans<<endl;
}
return 0;
}