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; }