Problem H: 玩具
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 281 Solved: 70
Description
商店有n个玩具,第i个玩具有价格a[i]和快乐值b[i]。有一天,小王来到商店想买一些玩具,商店老板告诉他,如果他买的所有玩具的位置是连续的,那么老板答应小王购买的所有玩具中某一个可以免费。小王接受老板的提议,他现在有零花钱k可以用来买玩具,那么他能获得的最大的快乐值是多少。
Input
第一行给测试总数T(T <= 100),接下来有T组测试数据。
每组测试数据第一行有两个数字n(1 <= n <= 5000)和k(0 <= k <= 1000000000)。
第二行有n个数字,第i个数字表示第i个玩具的价格a[i](1
<= a[i] <= 1000000)。
第三行有n个数字,第i个数字表示第i个玩具的快乐值b[i](1
<= b[i] <= 1000000)。
Output
每组测试输出小王能获得的最大快乐值。
Sample Input
3 5 14 1 2 3 4 5 5 4 3 2 1 3 1 100 1000 10000 100 1000 10000 1 0 1000000 1000000
Sample Output
15 10000 1000000
HINT
思路:因为是购买连续的物品,用尺取即可,区间最值从ST表中取出。
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <vector>
# include <cmath>
# include <cstdlib>
# define INF 0x3f3f3f3f
# define LL long long
using namespace std;
const int maxn=5003;
int h[maxn], v[maxn];
int mx[maxn][16];
int n,q;
void rmq_init()
{
int i,j,t;
for(j=1; j<=n; j++) mx[j][0] = h[j];
int m = floor(log((double)n) / log(2.0));
for(i=1; i<=m; i++){
for(j=1; j<=n; j++)
{
t = j+(1<<(i-1));
if(t<=n) mx[j][i] = max(mx[j][i-1], mx[t][i-1]);
else mx[j][i] = mx[j][i-1];
}
}
}
int rmq(int l,int r)
{
int m = floor(log((double)(r-l+1))/log(2.0));
int a = max(mx[l][m], mx[r-(1<<m)+1][m]);
return a;
}
int main()
{
int t, k;
scanf("%d",&t);
while(t--)
{
memset(mx, 0, sizeof(mx));
scanf("%d%d",&n,&k);
for(int i=1; i<=n; ++i)
scanf("%d",&h[i]);
rmq_init();
for(int i=1; i<=n; ++i)
scanf("%d",&v[i]);
int l=1, r=1, sum=h[1], tot=v[1], ans=v[1], imax=0;//sum为前缀和,tot为价值。
while(r <= n)//写的比较丑。
{
ans = max(ans , tot);
if(r == n)
break;
if(r+1 <= n && sum+h[r+1]-rmq(l, r+1)<=k)
{
++r;
tot += v[r];
sum = sum + h[r];
ans = max(ans, tot);
}
else
{
sum -= h[l];
tot -= v[l];
++l;
while( l< r && sum-rmq(l, r) > k)
{
sum -= h[l];
tot -= v[l];
++l;
}
}
}
printf("%d\n",ans);
}
return 0;
}

浙公网安备 33010602011771号