Description
E.Space 喜欢打音游。
但是他技术不好,总是拿不到全连(Full Combo)。
现在他面前有一份乐谱,乐谱的其中一段有 n个连续的单键音符。
相邻两个音符的到来时间均相等,我们可以认为第 i 个音符会在第 i 个时刻到来。
点击一个音符,E.Space 需要一段准备时间来进行移动手指之类的操作。由于音符的位置和周围情况不同,点击每个音符的准备时间也不同。
在一个音符的准备时间内,E.Space 没法做到去点击其它音符,但是不同音符的准备时间范围可以互相重叠。形式化地,令第 i 个音符的准备时间为 ti 个单位时间,那么如果 E.Space 选择去点击第 i 个音符,那么他就没法点击所有到来时刻在 (i−ti,i+ti) 中的音符。
为了获得更高的分数,E.Space 还计算了每个音符的性价比ai。一个音符的性价比等于点击这个音符得到的分数除以E.Space 点击它所需要的准备时间。
E.Space 就不指望全连了,他只是想让你帮他计算一下他最多可以得到多少分数。
n
<
=
1
0
6
∀
i
∈
[
1
,
n
]
,
a
i
<
=
1
0
9
n<=10^6\\\forall i\in [1,n],a_i<=10^9
n<=106∀i∈[1,n],ai<=109
Solution
fjwc题目的名字都啥啊,又是fc又是diff的
考虑dp,设f[i]表示前i个第i个一定选的答案,j能转移到i满足j+t[j]<=i,且j<=i-t[i]
于是这显然就是一个二维偏序问题,我一开始写了主席树结果空间被卡了。
实际上我们只需要按照i+t[i]排序然后维护前缀max直接做就没了,非常好写
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
#define lowbit(x) (x&-x)
#define fi first
#define se second
typedef long long LL;
typedef std:: pair <LL,int> pair;
const int N=1000005;
LL f[N],s[N],c[N];
int n;
pair p[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void upd(LL &x,LL v) {
(x<v)?(x=v):0;
}
LL get(int x) {
LL res=0;
for (;x;x-=lowbit(x)) upd(res,c[x]);
return res;
}
void add(int x,LL v) {
for (;x<=n;x+=lowbit(x)) upd(c[x],v);
}
int main(void) {
freopen("data.in","r",stdin);
n=read();
rep(i,1,n) s[i]=read();
rep(i,1,n) f[i]=s[i]*read();
rep(i,1,n) p[i]=pair(i+s[i],i);
std:: sort(p+1,p+n+1);
LL ans=0; int now=1;
rep(i,1,n) {
while (now<=n&&p[now].fi<=i) {
add(p[now].se,f[p[now].se]);
now++;
}
if (i-s[i]>0) f[i]+=get(i-s[i]);
upd(ans,f[i]);
}
printf("%lld\n", ans);
return 0;
//18724375936
}