掌中之物,未必在掌握之中。|

2021hych

园龄:2年7个月粉丝:2关注:2

[NOIP2015 普及组] 推销员题解

题型考察

此题的数据范围提示时间复杂度 为 O(n)O(nlogn) 考虑贪心。

思路

很明显对于每个 X,都要 O(1)O(logn) 进行回答,有两种思路,预处理和问题递进,这里使用问题递进。
所谓问题递进就是在 X 从小到大经过较少的调整得到新问题的解。在这里对于 X=1 ,显然问题的答案为:

max1insi×2+ai

记录当前取得最大值的住户为 bpos
考虑到 X=2。可以很容易的证明,答案一定是基于 X=1 的答案所扩展的,考虑多选择的住户为 i
i<bpos时,答案在原基础上增加 ai
i>bpos时,答案在原基础上增加 2×(sisbpos)+ai
如果要求答案最大,则
i<bpos时,使得 ai 最大,记答案为 ansL
i>bpos时,使得 2×si+ai 最大,记答案为 ansR
利用优先队列维护即可。
ansLansR 时,答案增加 ansR,可以发现,为了保持最优性,新的 bpos 为使得 2×si+ai 最大的住户,然后同时调整左右边的优先队列。
ansL>ansR 时,答案增加 ansL,可以发现,不需要调整 bpos,然后调整左边的优先队列。
上述过程考场上不用严格证明,手推样例即可领悟。
细节方面判断要特殊处理队空的情况。

代码实现

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,ans,bpos,ansL;
int s[N],a[N];
struct node {
	int pos,val;
	friend bool operator < (node x,node y) {
		return x.val<y.val;
	}
}qwq,ansR;
priority_queue<int>q1;
priority_queue<node>q2;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>s[i];
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) {
		qwq.pos=i;
		qwq.val=2*s[i]+a[i];
		q2.push(qwq);
	}
	for(int i=1;i<=n;i++) {
		ansL=ansR.val=0;
		if(!q1.empty()) ansL=q1.top();
		while(!q2.empty()&&q2.top().pos<=bpos) q2.pop();
		if(!q2.empty()) ansR=q2.top();
		if(ansL<ansR.val-2*s[bpos]) {
			ans+=ansR.val-2*s[bpos];
			for(int j=bpos+1;j<=ansR.pos-1;j++) q1.push(a[j]);
			bpos=ansR.pos;
			q2.pop();
		}
		else {
			ans+=ansL;
			q1.pop();
		}
		cout<<ans<<endl;
	}
	return 0;
}

本文作者:2021hych

本文链接:https://www.cnblogs.com/2021hych/p/16508138.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   2021hych  阅读(140)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起