【做题记录】[NOIP2011 提高组] 观光公交

P1315 [NOIP2011 提高组] 观光公交

我们想在 \(k\) 次加速每一次都取当前最优的方案加速。

考虑怎样计算对于每一条边如果在当前情况下使用加速器能够使答案减少的大小。

如果当前到达某个点时已经有人在等待了,那么加速这个点以前的边能够让这个点下车的人距离减少,而对于仍旧在车上的没有贡献。

如果到达这个点时车还需要等待人,那么加速之前的的边对车上人的影响会在以后的点(直至这些人下车时)再会计算,而能够让在这个点下车的人距离减少。

综上,我们发现减少一条边的距离会使在这个点下车的人距离减少,这个贡献保留到人等车的那一刻,所以我们就可以在 \(k\) 次加速每次处理到达这个点的时间与最后一个人到达的时间,到这取最大值即可。

#define Maxn 10005
int n,m,k,ans;
int Last[Maxn],cntup[Maxn],cntdown[Maxn],arr[Maxn],d[Maxn];
int s[Maxn],t[Maxn],x[Maxn];
int main()
{
	 n=rd(),m=rd(),k=rd();
	 for(int i=2;i<=n;i++) d[i]=rd();
	 for(int i=1;i<=m;i++)
	 {
	 	 x[i]=rd(),s[i]=rd(),t[i]=rd();
	 	 cntup[s[i]]++,cntdown[t[i]]++;
	 	 Last[s[i]]=max(Last[s[i]],x[i]);
	 	 ans-=x[i];
	 }
	 while(k--)
	 {
	 	 for(int i=1;i<=n;i++)
	 	 	 arr[i]=max(Last[i],arr[i-1]+d[i]);
	 	 int hav=0,MAX=0,pos=0;
	 	 for(int i=n;i>=2;i--)
	 	 {
	 	 	 if(arr[i]==Last[i]) hav=cntdown[i];
	 	 	 else
	 	 	 {
	 	 	 	 hav+=cntdown[i];
	 	 	 	 if(d[i] && hav>MAX) MAX=hav,pos=i;
			 }
		 }
		 if(pos) d[pos]--;
		 else break;
	 }
	 for(int i=1;i<=n;i++)
	 	 arr[i]=max(Last[i],arr[i-1]+d[i]),ans+=cntdown[i]*(arr[i-1]+d[i]);
	 printf("%d\n",ans);
	 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值