【NOIP2015】推銷員
推(chuan)銷員
分析
這裡主要闡述一下我的分析思路。
看起來挺直觀的。
最初的想法,我們列舉每一個最遠點mxp的位置,然後對之前的a進行排序。
那麼以mxp為最遠點,選x個的最大疲勞值為:
這樣的複雜度為
但是,我們要嘗試發現這道題的特性,來進行時間上的優化。
根據極大化思想,我們要儘可能排除不影響答案的
當
記
當
所以我們得到了決策單調性:對於
接下來,很容易想到用單調佇列什麼的進行維護。
但怎麼嘗試都覺得不行……
這時候就一定要跳出來啦。
根據決策單調性這個重要的特點,考慮換一種思考的角度。
假如當前
我們有兩種方法:
①在
②在
用兩個堆實現即可。
有點意思。
程式碼
#include <cstdio>
#include <cctype>
#include <queue>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define x first
#define y second
#define mp make_pair
typedef pair<int,int> PII;
const int N=131072;
int n;
int s[N],a[N];
int cur,vis[N];
priority_queue<PII> qs,qb;
int res;
inline int rd(void)
{
int x=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
int main(void)
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
n=rd();
rep(i,1,n) s[i]=rd();
rep(i,1,n) a[i]=rd();
rep(i,1,n)
qb.push(mp(2*s[i]+a[i],i));
PII t1,t2; int e1,e2,cs;
rep(i,1,n)
{
while (!qs.empty())
{
t1=qs.top();
if (vis[t1.y])
qs.pop();
else break;
}
while (!qb.empty())
{
t2=qb.top();
if (t2.y<cur||vis[t2.y])
qb.pop();
else break;
}
e1=(!qs.empty());
e2=(!qb.empty());
if (!e1&&e2)
cs=2;
else if (e1&&!e2)
cs=1;
else if (e1&&e2)
{
t1=qs.top(),t2=qb.top();
if (t2.x-2*s[cur]>=t1.x)
cs=2;
else cs=1;
}
if (cs==1)
{
t1=qs.top(); qs.pop();
vis[t1.y]=