堆维护,贪心做法

题目描述

阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有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时,阿明最多积累的疲劳值。


这题在2016年做过,不过全WA了hhh……

好吧今天提交4次前两次也是全WA……

最初的思路

假设现在右端点为i-1,有i优于j(i < j)那么有wi+2(s[i]-s[i-1])>wj+2(s[j]-s[i-1])即wi+2si>wj+2sj

定义距离s[],疲劳值w[],f[i]表示在i..n中(2si+wi)最大值的编号。那么我们每次处理1..now-1的w[]最大值和value(f[i+1])两者最大值。重复这一过程。

然而这个做法在调试时候就叉掉了……


第一次WA

非常NAIVE地把左右两边用了一个堆维护value()最小值,pretest过了就交了……

但是这个value()与max_right_border有关系,所以这个堆是个假堆……

 #include<bits/stdc++.h>
using namespace std;
const int N = 1e5;
int n,s[N],w[N],f[N],now,sum,rx;
bool vis[N];
int reval(int a)
{
if (a >= rx)return w[a]+*(s[a]-s[rx]);
return w[a];
}
struct cmp
{
bool operator () (int &a, int &b) const
{
return reval(a) < reval(b);
}
};
priority_queue<int, vector<int>, cmp> p,q;
int deal(int x)
{
if (x <= )return ;
while ((!q.empty())&&vis[q.top()])q.pop();
if (q.empty())return ;
return q.top();
}
int dear(int x)
{
while ((!p.empty())&&(vis[p.top()]))p.pop();
if (p.empty())return ;
return p.top();
}
int main()
{
scanf("%d",&n);
for (int i=; i<=n; i++)scanf("%d",&s[i]);
for (int i=; i<=n; i++){scanf("%d",&w[i]);p.push(i);}
f[n] = n;
for (int i=n-; i>=; i--)
if (*s[i]+w[i] > *s[f[i+]]+w[f[i+]])
f[i] = i;
else f[i] = f[i+];
now = ;rx = ;
for (int i=; i<=n; i++)
{
int dl = deal(now-);
int dr = dear(now+);
if (reval(dl) > reval(dr)){
now = dl;
vis[dl] = ;
sum += reval(dl);
}else{
sum += reval(dr);
if (rx < dr){
for (int j=now+; j<=dr; j++) q.push(j);
rx = dr;
}
now = dr;
vis[dr] = ;
}
printf("%d\n",sum);
}
return ;
}

第二次WA

观察变量调试重写了三十分钟,(此时并没有意识到假堆的严重性),看着调试输出还以为堆不假了(flag)。

在查询时候,又多放了一个堆来解决:查询左边时候q.top()却在now右边的情况(反之亦然)。这pretest设计得真好

按道理这样应该比第一次WA要慢一些,结果却快了200ms+...

反正都是全WA

 #include<bits/stdc++.h>
using namespace std;
const int N = 1e5;
int n,s[N],w[N],f[N],now,sum,rx;
bool vis[N];
int reval(int a)
{
if (a >= rx)return w[a]+*(s[a]-s[rx]);
return w[a];
}
struct cmp
{
bool operator () (int &a, int &b) const
{
return reval(a) < reval(b);
}
};
priority_queue<int, vector<int>, cmp> p,q;
int deal(int x)
{
if (x <= )return ;
queue<int>tt;
while ((!q.empty())&&(q.top()>now||vis[q.top()]))
{
while ((!q.empty())&&(vis[q.top()]))q.pop();
while ((!q.empty())&&(q.top()>now)){tt.push(q.top());q.pop();}
}
if (q.empty())return ;
int xx = q.top();
while (!tt.empty()){q.push(tt.front());tt.pop();}
return xx;
}
int dear(int x)
{
queue<int>tt;
if (rx == n)return ;
if(rx!=n)while ((!p.empty())&&(p.top()<now||vis[p.top()]))
{
while ((!p.empty())&&(vis[p.top()]))p.pop();
// printf("ptop:%d\n",p.top());
while((!p.empty())&&(p.top()<now)){tt.push(p.top());p.pop();}
}
if (p.empty())return ;
int xx = p.top();
while (!tt.empty()){p.push(tt.front());tt.pop();}
return xx;
}
int main()
{
scanf("%d",&n);
for (int i=; i<=n; i++)scanf("%d",&s[i]);
for (int i=; i<=n; i++){scanf("%d",&w[i]);p.push(i);}
f[n] = n;
for (int i=n-; i>=; i--)
if (*s[i]+w[i] > *s[f[i+]]+w[f[i+]])
f[i] = i;
else f[i] = f[i+];
now = ;rx = ;
// for (int i=1; i<=n; i++)printf("%d ",f[i]);printf("#\n");
for (int i=; i<=n; i++)
{
int dl = deal(now-);
int dr = dear(now+);
// printf("now:%d rx:%d dl:%d %d-dr:%d %d\n",now,rx,dl,reval(dl),dr,reval(dr));
if (reval(dl) >= reval(dr)){
now = dl;
vis[dl] = ;
sum += reval(dl);
}else{
sum += reval(dr);
if (rx < dr){
for (int j=rx+; j<=dr; j++) q.push(j);
rx = dr;
}
now = dr;
vis[dr] = ;
}
// for (int i=1; i<=n; i++)printf("%d ",vis[i]);puts("@");
printf("%d\n",sum);
}
int dl = deal(now-);
int dr = dear(now+);
// printf("now:%d rx:%d dl:%d %d-dr:%d %d\n",now,rx,dl,reval(dl),dr,reval(dr));
return ;
}

第一次TLE

好气啊打了一发纯粹的暴力(天哪有60分)

 #include<bits/stdc++.h>
using namespace std;
const int N = 1e5+;
int n,s[N],w[N],rx,now,sum;
int a,b;
bool vis[N];
int reval(int x)
{
if (x < rx)return w[x];
return w[x] + *(s[x]-s[rx]);
}
int main()
{
scanf("%d",&n);
for (int i=; i<=n; i++)scanf("%d",&s[i]);
for (int i=; i<=n; i++)scanf("%d",&w[i]);
for (int k=; k<=n; k++)
{
a = , b = ;
int cmp = , lb;
for (int i=; i<now; i++)
if ((!vis[i])&&(a < w[i]))a = w[b = i];
cmp = a;lb = b;
a = ,b = ;
for (int i=now+; i<=n; i++)
if ((!vis[i])&&(a < reval(i)))
a = reval(i),b = i;
if (a > cmp){cmp = a;lb = b;}
rx = max(rx, lb);
vis[lb] = ;
now = lb;
sum += cmp;
printf("%d\n",sum);
}
return ;
}

正解AC

在打完暴力之后豁然开朗(???)意识到右部分大于max_right_border的枚举即可,这样一来左边的就变为小于max_right_border的部分,由此无所谓在now左部分的元素变动情况,从而可以保证堆的正确性。

 #include<bits/stdc++.h>
using namespace std;
const int N = 1e5+;
int n,s[N],w[N],rx,now,sum;
int a,b;
bool vis[N];
struct cmp
{
bool operator() (int &a, int &b)
{
return w[a] < w[b];
}
};
priority_queue<int, vector<int>, cmp>q;
void find()
{
while ((!q.empty())&&(vis[q.top()]))q.pop();
if (q.empty())return;
b = q.top();a = w[b];
}
int main()
{
scanf("%d",&n);
for (int i=; i<=n; i++)scanf("%d",&s[i]);
for (int i=; i<=n; i++)scanf("%d",&w[i]);
for (int k=; k<=n; k++)
{
a = , b = ;
int cmp = , lb;
find();
cmp = a;lb = b;
a = ,b = ;
for (int i=rx+; i<=n; i++)
if ((!vis[i])&&(a < w[i] + *(s[i]-s[rx])))
a = w[i] + *(s[i]-s[rx]),b = i;
if (a > cmp)
{
cmp = a;
lb = b;
}
if (rx < lb)
{
for (int i=rx+; i<=lb; i++)q.push(i);
rx = lb;
}
vis[lb] = ;
now = lb;
sum += cmp;
printf("%d\n",sum);
}
return ;
}

【贪心 堆】luoguP2672 推销员的更多相关文章

  1. 【贪心+堆】XMU 1584 小明的烦恼

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1584 题目大意: 给n(n<=100 000)个任务的耗时和截至时间,问最少不能 ...

  2. BZOJ_2151_种树_贪心+堆+链表

    BZOJ_2151_种树_贪心+堆 Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编 ...

  3. BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表

    BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐 ...

  4. BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆

    BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是 ...

  5. 【bzoj4425】[Nwerc2015]Assigning Workstations分配工作站 贪心+堆

    题目描述 佩内洛普是新建立的超级计算机的管理员中的一员. 她的工作是分配工作站给到这里来运行他们的计算研究任务的研究人员. 佩内洛普非常懒惰,不喜欢为到达的研究者们解锁机器. 她可以从在她的办公桌远程 ...

  6. 【bzoj1029】[JSOI2007]建筑抢修 贪心+堆

    题目描述 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建 ...

  7. 【bzoj2802】[Poi2012]Warehouse Store 贪心+堆

    题目描述 有一家专卖一种商品的店,考虑连续的n天.第i天上午会进货Ai件商品,中午的时候会有顾客需要购买Bi件商品,可以选择满足顾客的要求,或是无视掉他.如果要满足顾客的需求,就必须要有足够的库存.问 ...

  8. BZOJ 1724: [Usaco2006 Nov]Fence Repair 切割木板 贪心 + 堆 + 反向思考

    Description Farmer John想修理牧场栅栏的某些小段.为此,他需要N(1<=N<=20,000)块特定长度的木板,第i块木板的长度为Li(1<=Li<=50, ...

  9. NOIP2015 T4 推销员 贪心+堆优化

    前几天在学堆,这个数据结构貌似挺简单的,但是我看了很久啊QAQ... 今天算是搞懂了吧...于是想到了这道题...(当初悄悄咪咪看题解记得一点) 点我看题 放洛谷的题... 题意的话,大概就是有n个房 ...

随机推荐

  1. [原创]内网渗透专用SSH连接工具sshcmd/sshshell/ssh密码破解以及Kali开启SSH

    目录 1.Kali开启SSH 2.SSH连接工具优缺点 3.渗透专用SSH连接工具 4.ssh执行cmd源码 5.批量SSH密码破解 6.相关工具下载 0x001 SSH配置 1.打开文件 etc/s ...

  2. 第三篇 Nosql讲解之windows下Memcached和Memcache的区别安装(二)

    一.Memcached和Memcache的区别: 网上关于Memcached和Memcache的区别的理解众说纷纭,我个人的理解是: Memcached是一个内存缓存系统,而Memcache是php的 ...

  3. hdu 6319 Problem A. Ascending Rating (2018 Multi-University Training Contest 3)

    #include <stdio.h> #include <iostream> #include <cstdlib> #include <cmath> # ...

  4. collections 中 typing 中对象的引用

    from typing import ( Callable as Callable, Container as Container, Hashable as Hashable, Iterable as ...

  5. scrapy框架中Item Pipeline用法

    scrapy框架中item pipeline用法 当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的pyt ...

  6. redis 的操作

    redis Redis(Remote Dictionary Server)是一个开源使用的非关系型数据库 通常被称为数据结构服务器,因为值可以是字符串,哈希,列表,集合,有序集合 优势 ​ 性能极高, ...

  7. python学习之模块:

    每个.py文件就是一个以文件名作为区别的模块,模块化编程便于维护.其它模块要调用某个模块的变量和函数就要用import 模块,然后通过模块.函数.模块.变量来引用. 为防止模块间变量和函数乃至模块名的 ...

  8. 通过Chrome执行watir-webdriver

    1.http://code.google.com/p/chromedriver/downloads/list  下载chromedriver驱动文件chromedriver.exe 2.把驱动文件放在 ...

  9. 最大流bfs

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #i ...

  10. asp.net mvc 使用uploadfiles 实现异步上传数据

    lesg.cn 文章发布在:  http://www.lesg.cn/netdaima/net/2017-990.html 在实际开发过程中, 为了提高用户的体验,在上传文件的时候通常会使用异步上传文 ...