题目:
题意:
求在一个长度为 n n n的数轴上,从原点出发,按照 a [ j ] ∗ ( j − i ) a[j] * (j - i) a[j]∗(j−i)的规则累计分数,最终到达 n n n时的最高分
分析:
一开始打出了一个
O
(
n
2
)
O(n^2)
O(n2)的
d
p
dp
dp,然后想方设法的想要压缩到
O
(
n
)
O(n)
O(n),但却没有想出来
后来听到
W
Y
C
WYC
WYC大爷说可以用贪心,然后证明了下正确性,就怒切了
.
.
..
..
贪心:我们从后往前统计最大值,然后每次跳都跳到该位置对应的最大值
正确性:
按照我们的思路,我们应该先从原点跳到
5
5
5,然后再跳到第二个
3
3
3,但会不会出现这样的情况呢:
这时
5
5
5到
3
3
3的长度改变了,那我们是不是应该直接到第二个
3
3
3呢
其实不然,如果直接跳到第二个
3
3
3,那么对于答案的贡献是
3
∗
(
100
+
5
)
3*(100+5)
3∗(100+5),如果先跳
5
5
5,那么对于答案的贡献就变成了
5
∗
5
+
3
∗
100
5*5+3*100
5∗5+3∗100
好像更赚耶,但这是为什么呢
因为我们前
5
5
5步可以选择的有
5
5
5和
3
3
3,而后
100
100
100步则只能选
3
3
3
既然要答案最大,那我们对于可以选更大的为什么不选呢
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/trie_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>
#define LL long long
using namespace std;
using namespace __gnu_pbds;
inline LL read(){
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int a[100005];
int maxa[100005];
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
int n=read();
for(int i=1;i<=n;i++) a[i]=read();
maxa[n]=a[n];
for(int i=n-1;i;i--) maxa[i]=max(a[i],maxa[i+1]);
int ans=0,last=0;
for(int i=1;i<=n;i++)
{
if(maxa[i]!=a[i]) continue;
ans+=a[i]*(i-last);
last=i;
}
cout<<ans;
return 0;
}