向前走莫回头❤

【codevs 5126】[NOIP2015 普及组T4]推销员(贪心)

5126 推销员 NOIP2015

 时间限制: 1 s   空间限制: 128000 KB   题目等级 : 黄金 Gold

题目描述 Description

 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有N家住户,第i家住户到入口的距离为Si米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的X家住户推销产品,然后再原路走出去。阿明每走1米就会积累1点疲劳值,向第i家住户推销产品会积累Ai点疲劳值。阿明是工作狂,他想知道,对于不同的X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。

输入描述 Input Description

 第一行有一个正整数N,表示螺丝街住户的数量。
 接下来的一行有N个正整数,其中第i个整数Si表示第i家住户到入口的距离。数据保证S1≤S2≤…≤Sn<10^8。
 接下来的一行有N个正整数,其中第i个整数Ai表示向第i户住户推销产品会积累的疲劳值。数据保证Ai<10^3。

输出描述 Output Description

 输出N行,每行一个正整数,第i行整数表示当X=i时,阿明最多积累的疲劳值。

样例输入 Sample Input

 【样例1】
  5
  1 2 3 4 5
  1 2 3 4 5

【样例2】
 5
 1 2 2 4 5
 5 4 3 4 1

样例输出 Sample Output

 【样例1】
  15
   19
   22
   24
   25

 【样例2】
   12
   17
   21
   24
   27

数据范围及提示 Data Size & Hint  

  1≤N≤100000

【题解】【贪心】

【刚开始写了个dp,O(n³),写完看数据范围就傻了。。。】

[40分码]

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[5010][5010],g[5010][5010];
int n,a[100010],len[100010];
int main()
{
	int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;++i)scanf("%d",&len[i]);
	for(i=1;i<=n;++i)scanf("%d",&a[i]);
	f[1][1]=len[1]*2+a[1]; 
	g[1][1]=1;
	for(i=2;i<=n;++i)
	 for(j=1;j<=i;++j)
	  {
	  	f[i][j]=f[i-1][j]; g[i][j]=g[i-1][j];
	  	for(int k=j-1;k<i;++k)
	  	 {
	  	 	int sum=f[k][j-1]+(len[i]-len[g[k][j-1]])*2+a[i];
	  	    if(sum>f[i][j]) f[i][j]=sum,g[i][j]=i;
		   }
		int sum=f[i-1][j-1]+(len[i]-len[g[i-1][j-1]])*2+a[i];
	  	if(sum>f[i][j]) f[i][j]=sum,g[i][j]=i;
	  }
	for(i=1;i<=n;++i)printf("%d\n",f[n][i]);
	return 0;
}

【看上去十分科学,然而。。。】

【于是想把dp的实现过程改成线段树,因为这明显是区间取最优值的问题。但由于我从没写过,果断弃了】

【开始乱搞贪心:最后想到应该是尽量取推销时疲劳值大的,然后按路程为第一关键字排序,从小到大排,疲劳值为第二关键字排序,因为最优值一定是在前一次的最优值基础上出现的(这并不是说下一次再找当前情况下的最大权值),即所以找的时候可以继承上一次的查找位置。但是,按照排序后的顺序顺次取,不一定是最优的,每次要向后枚举看有没有更优的,下一次时,就接着上一次最优值的位置继续查找。优先队列维护】

[在vijos上莫名WA掉。。。]

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
	int val,road;
	bool operator<(const node &a)const
	 {
	 	return a.val>val;	 
	}
}a[100010];
priority_queue<node>que;
int n,num[100010],nm[100010],tot,ans;
int tmp(node a,node b)
{
	return (a.road<b.road||a.road==b.road&&a.val>b.val);
}
int main()
{
	int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;++i)scanf("%d",&a[i].road);
	for(i=1;i<=n;++i)scanf("%d",&a[i].val);
	sort(a+1,a+n+1,tmp);
	for(i=1;i<=n;++i)
	 if(a[i-1].road==a[i].road) nm[tot]=i;
	  else num[++tot]=i,nm[tot]=i;
	int last=0;
	node x; x.road=x.val=0;que.push(x);
	for(i=1;i<=n;++i)
	 {
	 	node x=que.top(); 
	 	int maxn=x.val,t=last; 
	 	for(int j=last+1;j<=tot;++j)
	 	 {
	 	 	int u=num[j];
	 	 	int sum=a[u].val+(a[u].road-a[last].road)*2;
	 	 	if(sum>maxn) sum=maxn,t=j;
		  }
		int u=num[t];
		a[u].val+=(a[u].road-a[last].road)*2;
		for(int j=nm[last]+1;j<=nm[t];++j) que.push(a[j]);
		x=que.top(); que.pop();
		ans+=x.val; last=t;
		printf("%d\n",ans);
	 }
	return 0;
}


#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 100005

int n,Max,maxp,point;
int s[N],a[N],pt[N],ans[N];
bool vis[N];
struct hp
{
    int val,loc;
    bool operator < (const hp &a) const
    {
        return a.val>val;
    }
};
priority_queue <hp> q;
priority_queue <hp> p;


int main()
{
    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]);
    for (int i=1;i<=n;++i)
        if (a[i]+2*s[i]>=Max)
        {
            Max=a[i]+2*s[i];
            maxp=i;
        }

    for (int i=1;i<=maxp;++i)
    {
        hp now;now.loc=i,now.val=a[i];
        q.push(now);
    }
    for (int i=maxp+1;i<=n;++i)
    {
        hp now;now.loc=i,now.val=a[i]+s[i]*2;
        p.push(now);
    }
    point=maxp+1;vis[maxp]=true;
    ans[1]=Max;pt[1]=maxp;
    for (int i=2;i<=n;++i)
    {
        hp l,r;l.val=l.loc=r.loc=r.val=0;
        if (!q.empty()) l=q.top();
        if (!p.empty()) r=p.top();
        while (vis[l.loc])
        {
            l.val=l.loc=0;
            if (!q.empty()) q.pop(),l=q.top();
        }
        while (vis[r.loc])
        {
            r.val=r.loc=0;
            if (!p.empty()) p.pop(),r=p.top();
        }
        if (!r.val||(l.val!=0&&ans[i-1]+l.val>ans[i-1]+r.val-2*s[pt[i-1]]))
        {
            if (!q.empty()) q.pop();
            vis[l.loc]=true;
            pt[i]=pt[i-1];
            ans[i]=ans[i-1]+l.val;
        }
        else
        {
            if (!p.empty()) p.pop();
            vis[r.loc]=true;
            pt[i]=r.loc;
            ans[i]=ans[i-1]+r.val-2*s[pt[i-1]];
        }
        for (int j=point;j<=pt[i];++j)
        {
            hp now;now.loc=j,now.val=a[j];
            q.push(now);
        }
        point=pt[i]+1;
    }
    for (int i=1;i<=n;++i) printf("%d\n",ans[i]);
}


posted @ 2016-11-03 14:42  lris0-0  阅读(166)  评论(0编辑  收藏  举报
过去的终会化为美满的财富~o( =∩ω∩= )m