全连
11374: 全连
时间限制: 1 Sec 内存限制: 256 MB提交: 15 解决: 3
[提交] [状态] [命题人:admin]
题目描述
还记得若干年前那段互相比较《克罗地亚狂想曲》的分数的日子吗?
E.Space 喜欢打音游。
但是他技术不好,总是拿不到全连(Full Combo)。
现在他面前有一份乐谱,乐谱的其中一段有 n 个连续的单键音符。
相邻两个音符的到来时间均相等,我们可以认为第 i 个音符会在第 i 个时刻到来。
点击一个音符,E.Space 需要一段准备时间来进行移动手指之类的操作。由于音符的位置和周围情况不同,点击每个音符的准备时间也不同。
在一个音符的准备时间内,E.Space 没法做到去点击其它音符,但是不同音符的准备时间范围可以互相重叠。形式化地,令第 i 个音符的准备时间为 ti个单位时间,那么如果 E.Space 选择去点击第 i 个音符,那么他就没法点击所有到来时刻在 (i−ti ,i+ti)中的音符。
为了获得更高的分数,E.Space 还计算了每个音符的性价比。一个音符的性价比等于点击这个音符得到的分数除以 E.Space 点击它所需要的准备时间。
E.Space 就不指望全连了,他只是想让你帮他计算一下他最多可以得到多少分数。
E.Space 喜欢打音游。
但是他技术不好,总是拿不到全连(Full Combo)。
现在他面前有一份乐谱,乐谱的其中一段有 n 个连续的单键音符。
相邻两个音符的到来时间均相等,我们可以认为第 i 个音符会在第 i 个时刻到来。
点击一个音符,E.Space 需要一段准备时间来进行移动手指之类的操作。由于音符的位置和周围情况不同,点击每个音符的准备时间也不同。
在一个音符的准备时间内,E.Space 没法做到去点击其它音符,但是不同音符的准备时间范围可以互相重叠。形式化地,令第 i 个音符的准备时间为 ti个单位时间,那么如果 E.Space 选择去点击第 i 个音符,那么他就没法点击所有到来时刻在 (i−ti ,i+ti)中的音符。
为了获得更高的分数,E.Space 还计算了每个音符的性价比。一个音符的性价比等于点击这个音符得到的分数除以 E.Space 点击它所需要的准备时间。
E.Space 就不指望全连了,他只是想让你帮他计算一下他最多可以得到多少分数。
输入
第一行一个正整数 n 。
第二行 n 个正整数,第 i 个正整数表示 ti。
第三行 n 个正整数,第 i 个正整数表示第 i 个音符的性价比 ai。
第二行 n 个正整数,第 i 个正整数表示 ti。
第三行 n 个正整数,第 i 个正整数表示第 i 个音符的性价比 ai。
输出
一行一个正整数,表示 E.Space 可能达到的最高分数。
样例输入
5
2 3 2 1 2
3 1 2 9 4
样例输出
18
提示
E.Space 可以选择点击第 1,3,5 个音符,分数为 2×3+2×2+2×4=18 。
保证 ti≤n,ai≤109
#include<bits/stdc++.h> #define REP(i, a, b) for(int i = (a); i <= (b); ++ i) #define REP(j, a, b) for(int j = (a); j <= (b); ++ j) #define PER(i, a, b) for(int i = (a); i >= (b); -- i) using namespace std; const int maxn = 1e6 + 5; template <class T> inline void rd(T &ret) { char c; ret = 0; while ((c = getchar()) < '0' || c > '9'); while (c >= '0' && c <= '9') { ret = ret * 10 + (c - '0'), c = getchar(); } } typedef long long ll; int t[maxn]; ll ans, dp[maxn], cur, p[maxn*4]; struct node { int now; bool operator<(const node &tmp)const { return now + t[now] > tmp.now + t[tmp.now]; } }; priority_queue<node>q; void update(int root, int l, int r, int cur, ll val) { if (l == r) { p[root] = val; //cout<<p[root]<<endl; return; } int mid = l + r >> 1; if (cur <= mid)update(root << 1, l, mid, cur, val); else update(root << 1 | 1, mid + 1, r, cur, val); p[root] = max(p[root << 1], p[root << 1 | 1]); return; } long long query(int root, int l, int r, int ql, int qr) { if (ql > qr)return 0; if (ql <= l && qr >= r)return p[root]; int mid = l + r >> 1; if (mid < ql)return query(root << 1 | 1, mid + 1, r, ql, qr); if (mid >= qr)return query(root << 1, l, mid, ql, qr); return max(query(root<<1,l,mid,ql,qr),query(root<<1|1,mid+1,r,ql,qr)); } int main() { int n; cin >> n; for (int i = 1; i <= n; i++)cin >> t[i]; for (int i = 1; i <= n; i++) { cin >> cur; dp[i] = cur * t[i]; while (!q.empty()) { node tmp = q.top(); if (tmp.now + t[tmp.now] > i)break; q.pop(); update(1,1,n,tmp.now,dp[tmp.now]); } //cout<<"******"<<endl; dp[i] += query(1,1,n,1,i-t[i]); ans = max(ans, dp[i]); q.push(node{ i }); } cout << ans << endl; return 0; }