题目链接:http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4273
题意:商店有n个玩具,第i个玩具有价格a[i]和快乐值b[i],小王用零花钱k买连续的玩具,老板答应他买的玩具中有一个可以免费,求小王获得的最大的快乐值。
解题思路:连续区间,求最大。用尺取法+set维护(PS:直接遍历i–j区间的最大值也能过)
#include<iostream>
#include<set>
using namespace std;
const int maxn = 5005;
int a[maxn], b[maxn];
int ChiQu(int n, int k){//n个玩具 零花钱k
int i = 0, j = 0;
int sum = 0, v = 0;
int ret = 0;
set<int> s;
while(1){
while(j < n){//sum 累加金钱数
s.insert(a[j]);
set<int>::iterator it = s.end();
//set的最后一个元素为集合的最大值
if(sum + a[j] - *(--it) > k) break;
//sum - 减免的玩具价格不能大于k
sum += a[j];
v += b[j++];
}
if(j < n) s.erase(a[j]);
ret = max(v , ret);
if(j == n || i >= j) break;
v -= b[i];
s.erase(a[i]);
sum -= a[i++];
}
return ret;
}
int main(){
int t;
cin >> t;
while(t--){
int n, k;
cin >> n >> k;
for(int i = 0; i < n; i++)
cin >> a[i];
for(int i = 0; i < n; i++)
cin >> b[i];
cout << ChiQu(n, k) << endl;
}
}
自己多给出的测试数据:
7 33
62 37 20 22 15 21 23
88 64 33 36 37 26 28
7 33
30 37 20 62 15 21 23
30 64 33 61 37 26 28
RMQ(Range Minimum/Maximum Query)算法:用户每输入一个查询便马上处理一个查询的在线处理算法。预处理时间O(nlogn),查询时间O(1)
简单说,就是用动态规划先存储区间的最大数,然后查询的时候可以取来用。
void init_RMQ()
{
for(int i = 1; i <= n; i++) dp[i][0]=a[i];
for(int j = 1; (1<<j) <= n; j++)
for(int i = 1;i + (1<<j) <= n+1; i++)
dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
}
int RMQ(int i,int j)
{
int k = log2(j-i+1);
while((1<<(k+1)) <= j-i+1) k++;
return max(dp[i][k], dp[j-(1<<k)+1][k]);
}