D
题意:
N长度的数组A .Q 次询问。
每一次询问:
bi k
分析:
先对A 排序。我们可以二分距离d,在区间[b-d,b+d]内的A 数组中数字的个数具有单调性。我们要找到满足 个数>=k 的最小值。至于A 数组中元素的个数,我们可以使用 upper_bound 和 lower_bound 来计算下标。两个下标之间的差+1 就是 和 b 的距离小于等于 d 的点。
当时看完这道题之后,感觉应该使用二分。但是不知道要二分什么。怎么check 。当时 ,还不知道要怎么处理这个距离。看了题解才明白。loser~~
再次感叹 二分答案的美妙之处。包括三分答案。只用外面套一层log 的代价。就可以 由 构造答案,转化成 检验答案。大部分情况下后者比前者容易much。
一定要想到二分啊~~
时间复杂度为 nlog^2
#include <bits/stdc++.h>
using namespace std;
int b,k;
vector<int>a;
int check(int d)
{
int m=lower_bound(a.begin(),a.end(),b-d)-a.begin();
int n=upper_bound(a.begin(),a.end(),b+d)-a.begin()-1 ;
return n-m+1;
}
void solve()
{
int n,q;cin>>n>>q;
a.resize(n);
for (int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a.begin(),a.end());
while(q--)
{
cin>>b>>k;
//枚举 靠近b 的第K个点,的距离
int l=0;int r=3e8;
while(l<=r)
{
int mid=l+r>>1;
if (check(mid)>=k)r=mid-1;
else l=mid+1;
}
cout<<r+1<<"\n";
}
}
int main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
int t; t=1;
//cin>>t;
while(t--)
{
solve();
}
return 0;
}
E:
我发现我看 数据范围的意识不是很强 ,赛时根本没有注意到 小的离谱的 N(只有80),反而一门心思扑在了 我想出来的错误的贪心上。以后一定要有看 数据范围的习惯啊~~
**对于某些状态较多,但是dp 值域比较小的动态规划。我们可以考虑将其中的一维信息和值域交换。采用交换权值的办法。达到降低dp的时间复杂度的目的。**背包问题。注意到非常小的N,尝试使用dp解决问题。定义dp[i][j][k] 表示 考虑前i 个物品,甜度为j ,咸度为k ,最多吃的菜数为 dp[i][j][k].但因为j k 的数值到1e4,所以这样设计必然超时。因为n 很小,也就是dp 的值域很小。可以将 值域和咸度的信息交换。重新定义dp[i][j][k] 表示考虑前i 个物品,吃的菜的数量是j 甜度是 k, 此时最小的咸度。
一个小细节:我们可以吃 超过的,dp 是合法的。所以最后会有一个 min(n,i+1)
转移:转移的时候,注意一下。一开始写的是 被注释掉的一行,直接程序崩溃了。
#include <bits/stdc++.h>
using namespace std;
const int N=85;
const int M=1e4+5;
int dp[N][N][M];
void solve()
{
int n,x,y;cin>>n>>x>>y;
vector<int>a(n+1);
vector<int>b(n+1);
for (int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
}
memset(dp,0x3f,sizeof(dp));
dp[0][0][0]=0;
for (int i=1;i<=n;i++)
{
for (int j=0;j<=i;j++)
{
for (int k=0;k<=x;k++)
{
dp[i][j][k]=min(dp[i-1][j][k],dp[i][j][k]);
// dp[i][j][k]=min(dp[i-1][j][k],dp[i-1][j-1][k-a[i]]+b[i]);
if (j&&k>=a[i])dp[i][j][k]=min(dp[i-1][j-1][k-a[i]]+b[i],dp[i][j][k]);
}
}
}
int ans=0;
for(int i=0;i<=n;i++)
{
for (int j=0;j<=x;j++){
if (dp[n][i][j]<=y)ans=max(ans,min(n,i+1));
}
}
cout<<ans<<"\n";
}
int main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
int t; t=1;
//cin>>t;
while(t--)
{
solve();
}
return 0;
}