题解:P10381 「HOI R1」杂赛选比
转化成在
最小代价转换成最短路,对于每个
感觉比线段树好多了啊!
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<utility>
#include<queue>
#define int long long
using namespace std;
const int MAXN=1e5+10,MAXM=2e5+10,INF=1e15;
int T,n,a[MAXN],s[MAXN],dis[MAXN],ans;
int to[MAXM],nxt[MAXM],head[MAXN],val[MAXM],cnt;
typedef pair<int,int> P;bool vis[MAXN];
inline void add(int x,int y,int v)
{
to[++cnt]=y,nxt[cnt]=head[x];
head[x]=cnt,val[cnt]=v;return ;
}
inline void dij()
{
priority_queue < P,vector<P>,greater<P> > q;
q.push({dis[1]=0,1});
while(!q.empty())
{
int x=q.top().second;q.pop();
if(vis[x]) continue;vis[x]=true;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];if(dis[y]<=dis[x]+val[i]) continue;
q.push({dis[y]=dis[x]+val[i],y});
}
}
}
inline void work()
{
cin>>n,cnt=ans=0;
for(int i=1;i<=n;++i) head[i]=vis[i]=0,dis[i]=INF;
for(int i=1;i<=n;++i)
{
cin>>a[i],s[i]=s[i-1]+a[i];
if(i>1) add(i,i-1,0);add(i,min(i+a[i],n),a[i]);
}
dij();for(int i=1;i<=n;++i) ans=max(ans,s[i]-dis[i]);
cout<<ans<<'\n';return ;
}
signed main()
{
#ifdef ONLINE_JUDGE
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(0);
#else
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
cin>>T;while(T--) work();
return 0;
}