NOIP2011 观光公交 加强版

传送门

题目大意

给定从左到右的$n$个车站以及两两之间通行的需要的时间。

有$m$个人,第$i$个人会在$T_i$时刻出现在$a_i$车站,目的地是$b_i$。

一辆车第$0$时刻出现在一号站台,从左向右驶去,每经过一个车站(包括$1$号),它会等待知道所有应该在该站台出现的乘客都出现才会继续驶向下一个站台。

定义一个人花费的时间是列车到达$b_i$的时刻$-T_i$。你有$k$次机会使得某相邻两站花费的时间减少一个时间单位(需要始终保证非负),求这$m$个人花费时间之和的最小值。

 

题解

在$n,m,k$均很小的情况下可以用各种算法搞过去,但加强后不得不优化复杂度。

前置技能:$O(nk)$的贪心(你可以在洛谷中找到大量的题解

先设一个最终答案为$ans$,初始时$ans=-\sum T_i$

仍是考虑设第$i$个车站最后一个人到达时间为$G_i$,到达$i$的时间比$G_i$多出了$S_i$的时间,第$i$个车站到第$i+1$个车站的距离为$D_i$。

那么$S_i=\max\{S_{i-1}+G_{i-1}+D_{i-1}-G_{i}\},ans+=S_i+G_i$

考虑一段区间$[L,R]$,若有$(L,R]$内的$S$均大于$0$,那么减少$D_L K$个单位可以使得所有$(L,R]$的到达时间减少$K$,那么最终答案减少的就是$K\times$区间内是终点的数量。

考虑用线段树维护$S$,将每一个有意义的$[L,R]$用一个大根堆存起来(以区间内终点数量为关键字)。

每次取出堆顶$[L,R]$,求$x=\min\{D_L,\min\{S_i\}i\in(L,R]\}$即为区间内可以减少的时间,那么将$k$次机会中的$x$个用与减少区间答案。

接下来一定会至少出现一个$i$使得$S_i=0$或$k=0$或$D_L=0$,那么原来有意义的区间至多分裂成两个有意义的区间,在分别丢进堆里不断处理即可。

可见,该算法的复杂度及基本与$k$无关,甚至与$m$无关。

复杂度仅为有意义的区间数量(不超过$2n$个)在带一个线段树的和堆的$log$,大概就是$O(n\log n)$。

 

#include<bits/stdc++.h>
#define LL long long
#define M 600020
using namespace std;
namespace IO{
	const int BS=(1<<20)+5; char Buffer[BS],*HD,*TL;
	char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
	int read(){
		int nm=0,fh=1; char cw=Getchar();
		for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
		for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
		return nm*fh;
	}
}using namespace IO;
int n,m,p[M<<2],pos[M<<2],tg[M<<2],val[M],D[M],K,last;
LL ans,gt[M],st[M];
#define pushup int sn=(p[x<<1]<p[x<<1|1])?(x<<1):(x<<1|1);pos[x]=pos[sn],p[x]=p[sn]
struct seg{
	int LS,RS;seg(){}
	seg(int _LS,int _RS){LS=_LS,RS=_RS;}
	bool operator<(const seg&ot)const{return val[RS]-val[LS]<val[ot.RS]-val[ot.LS];}
};priority_queue<seg>H;
void build(int x,int l,int r){
	if(l==r){pos[x]=r,p[x]=st[r];return;}
	int mid=((l+r)>>1); build(x<<1,l,mid);
	build(x<<1|1,mid+1,r); pushup;
}
#define pushdown tg[x<<1]+=tg[x],tg[x<<1|1]+=tg[x],p[x<<1]-=tg[x],p[x<<1|1]-=tg[x],tg[x]=0
void mdf(int x,int l,int r,int ls,int rs,int dt){
	if(ls<=l&&r<=rs){tg[x]+=dt,p[x]-=dt;return;}
	if(r<ls||rs<l) return; int mid=((l+r)>>1); pushdown;
	mdf(x<<1,l,mid,ls,rs,dt),mdf(x<<1|1,mid+1,r,ls,rs,dt); pushup;
}
int getnode(int x,int l,int r,int ls,int rs){
	if(ls<=l&&r<=rs) return x;if(r<ls||rs<l) return 0;
	int mid=((l+r)>>1); pushdown;
	int t1=getnode(x<<1,l,mid,ls,rs);
	int t2=getnode(x<<1|1,mid+1,r,ls,rs);
	return p[t1]>p[t2]?t2:t1;
}
int main(){
	n=read(),m=read(),K=read(),last=1,p[0]=1000000000;
	for(int i=1;i<n;i++) D[i]=read();
	for(int i=1;i<=m;i++){
		int tim=read(),x=read(),y=read();
		gt[x]=max(gt[x],(LL)tim),val[y]++,ans-=tim;
	}
	for(int i=2;i<=n;i++) val[i]+=val[i-1];
	for(int i=2;i<=n;i++){
		st[i]=max(0ll,st[i-1]+gt[i-1]+D[i-1]-gt[i]);
		if(!st[i]) H.push(seg(last,i)),last=i;
		ans+=(LL)(val[i]-val[i-1])*(gt[i-1]+st[i-1]+D[i-1]);
	}
	if(last<n) H.push(seg(last,n)); build(1,2,n);
	while(K>0&&!H.empty()){
		seg tmp=H.top();H.pop();int ls=tmp.LS,rs=tmp.RS,k=0;
		if(ls+1<rs) k=getnode(1,2,n,ls+1,rs-1);
		int dt,ks,t2=D[ls]; dt=min(K,min(t2,p[k])),ks=(dt==t2?ls+1:pos[k]);
		ans-=(LL)dt*(LL)(val[rs]-val[ls]),K-=dt; if(K<=0) break;
		if(dt&&ls+1<rs) mdf(1,2,n,ls+1,rs-1,dt); D[ls]-=dt;
 		if(ls<ks) H.push(seg(ls,ks)); if(ks<rs) H.push(seg(ks,rs));
	} printf("%lld\n",ans); return 0;
}

 

转载于:https://www.cnblogs.com/OYJason/p/9910831.html

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值