題目描述
阿明是一名推銷員,他奉命到螺絲街推銷他們公司的產品。螺絲街是一條死衚衕,出口與入口是同一個,街道的一側是圍牆,另一側是住戶。螺絲街一共有N家住戶,第i家住戶到入口的距離爲Si米。由於同一棟房子裏可以有多家住戶,所以可能有多家住戶與入口的距離相等。阿明會從入口進入,依次向螺絲街的X家住戶推銷產品,然後再原路走出去。
阿明每走1米就會積累1點疲勞值,向第i家住戶推銷產品會積累Ai點疲勞值。阿明是工作狂,他想知道,對於不同的X,在不走多餘的路的前提下,他最多可以積累多少點疲勞值。
輸入格式:
第一行有一個正整數N,表示螺絲街住戶的數量。
接下來的一行有N個正整數,其中第i個整數Si表示第i家住戶到入口的距離。數據保證S1≤S2≤…≤Sn<10^8。
接下來的一行有N個正整數,其中第i個整數Ai表示向第i戶住戶推銷產品會積累的疲勞值。數據保證Ai<10^3。
輸出格式:
輸出N行,每行一個正整數,第i行整數表示當X=i時,阿明最多積累的疲勞值。
輸入輸出樣例
輸入樣例#1:
5
1 2 3 4 5
1 2 3 4 5
輸出樣例#1:
15
19
22
24
25
輸入樣例#2:
5
1 2 2 4 5
5 4 3 4 1
輸出樣例#2:
12
17
21
24
27
解題思路:
這道題目可以有兩種做法,一種是貪心,一種是線段樹。
貪心如何去做呢?首先,要按照每戶的疲勞度去從大到小排序,然後,逐個去搜索,即可得到答案。
線段樹的話~~~這種模板,應該就用不着解釋了吧~~~
代碼:(請不要直接拷貝哦)
//貪心
#include <cstdio>
#include <algorithm>
struct pl{
int s,val;
}a[100005];
int maxx,j,k,ans;
using namespace std;
bool cmp(pl x,pl y)
{
return x.val>y.val;//按照向每家推銷的疲勞度排序
}
int main()
{
int n;
//freopen("1.in","r",stdin);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i].s);
for (int i=1;i<=n;i++) scanf("%d",&a[i].val);
sort(a+1,a+n+1,cmp);
for (int i=1;i<=n;i++)
if (2*a[i].s+a[i].val>maxx)//噹噹前這戶人家來回的疲勞度+推銷的疲勞度最大時,這就是我們需要找到的第一個答案
{
maxx=2*a[i].s+a[i].val;//記錄下來
j=k=i;//記住這個點,下次搜尋時這個點不要再算了,否則會WA的
}
ans+=maxx;
printf("%d\n",ans);
for (int i=1;i<=n;i++)
{
if (i==k) continue;//搜尋過了,直接跳過
if (a[j].s<a[i].s)
{
ans=ans-2*a[j].s+2*a[i].s+a[i].val;//重新計算答案
j=i;
printf("%d\n",ans);
} else
{
ans+=a[i].val;
printf("%d\n",ans);
}
}
return 0;
}
===========================================================================
//線段樹
#include <cstdio>
#include <algorithm>
struct TREE{
int l,r,mid,lazy,number,val;
}tree[400005];
int s[100005],a[100005];
int ans,now,last;
using namespace std;
inline void push_up(int x)
{
if (tree[x*2].val>=tree[x*2+1].val)
{
tree[x].number=tree[x*2].number;
tree[x].val=tree[x*2].val;
} else
{
tree[x].number=tree[x*2+1].number;
tree[x].val=tree[x*2+1].val;
}
}
inline void push_down(int x)
{
tree[x*2].val+=tree[x].lazy;
tree[x*2+1].val+=tree[x].lazy;
tree[x*2].lazy+=tree[x].lazy;
tree[x*2+1].lazy+=tree[x].lazy;
tree[x].lazy=0;
}
inline void build(int x,int l,int r)
{
tree[x].l=l,tree[x].r=r,tree[x].mid=(l+r)/2;
if (l==r)
{
tree[x].number=l;
tree[x].val=s[l]*2+a[l];
return;
}
build(x*2,l,tree[x].mid);
build(x*2+1,tree[x].mid+1,r);
push_up(x);
}
inline void change(int x)
{
if (tree[x].r<=last) return;
if (tree[x].l>now)
{
tree[x].val-=(s[now]-s[last])*2;
tree[x].lazy-=(s[now]-s[last])*2;
return;
}
if (tree[x].l==tree[x].r)
{
tree[x].val=a[tree[x].l];
return;
}
if (tree[x].lazy) push_down(x);
change(x*2);
change(x*2+1);
push_up(x);
}
inline void xg(int x)
{
if (tree[x].l==tree[x].r)
{
tree[x].val=-600000000;
return;
}
if (now<=tree[x].mid) xg(x*2);
else xg(x*2+1);
push_up(x);
}
int main()
{
int n;
//freopen("1.in","r",stdin);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&s[i]);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);//建樹
for (int i=1;i<=n;i++)
{
ans+=tree[1].val;//算答案,第一個即爲我們想要的值
now=tree[1].number;
printf("%d\n",ans);
if (now>last)
{
change(1);//改變樹
last=now;//更新last
}
xg(1);//將now刪除掉
}
return 0;
}