网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
08月02日漏签0天
c语言吧 关注:798,914贴子:4,358,058
  • 看贴

  • 图片

  • 吧主推荐

  • 视频

  • 游戏

  • 9回复贴,共1页
<<返回c语言吧
>0< 加载中...

讨论一个有些难度的算法题

  • 只看楼主
  • 收藏

  • 回复
  • 逢部祝
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
n件商品放在一个圆环形的展台上,按顺时针排列,它们的价格分别为P_0,P_1,...,P_{n-1},标注在一个位于展台正上方的圆形标签架上,每个标签标注了它正下方的商品价格
小明希望购买所有的n件商品,但是觉得都买下来太贵了。商店老板提供了一个有趣的选择,允许小明转动展台,但但展台上方的标签架不会跟着转动。转动展台的方向是顺时针,并且一次转动只能让商品错位一个位置(可以转动多次让商品错位到不同的位置),此时可以认为所有商品的价格进行了一次“洗牌”。转动展台后,小明就可以按照商品新的价格来购买商品了。转动一次展台需要花费X
问小明至少要花多少钱买下所有的商品。
输入:
商品件数n,商品价格P_0,P_1,...,P_{n-1},转动一次展台的花费X
输出:
购买所有商品的最小花费
样例1:
输入:3 [20,1,15] 5
输出:13
说明:先购买商品1(花费1),然后转动一次展台(花费5),价格变为[1,15,20],购买商品0(花费1),再转动一次展台(花费5),价格变为[15,20,1],最后购买商品2(花费1),总花费1+5+1+5+1=13
样例2:
输入:3 [1,2,3] 6
输出:6
说明:不需要转动展台,直接购买所有商品1+2+3=6
数据规模:
所有的P_i和X,均在32位有符号整型正整数的表示范围内
对于60%的数据,1 <= n <= 1000
对于100%的数据,1 <= n <= 1e6


  • simulacrumbd
  • 毛蛋
    1
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
//不知道行不行
#include <math.h>
#include <time.h>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <stack>
#include <fstream>
#include <algorithm>
#include <string>
#include <cstring>
#include <iostream>
#include <stdio.h>
#include <bitset>
using namespace std;
typedef long long item;
typedef long long _ll;
#define ls s<<1
#define rs s<<1|1
#define ri register int
#define mod 1000007
inline item read()
{
item f = 1, ret = 0;
char c = getchar();
while (c < 48 || c>57){if (c == '-')f = -f;c = getchar();}
while (c >= 48 && c <= 57){ret = ret * 10 + c - 48;c = getchar();}
return f * ret;
}
int n, q[2000004], h, t, ll, rr;
_ll x, dat[2000004], sum1, sum2, ans = 0x3f3f3f3f3f3f3f3f;
void check(_ll & sum,int k) {
sum = x * k; h = t = 0;
for (ri i = n+k; i > n; --i) {
while (h != t && dat[i] <= dat[q[t-1]])
--t;
q[t++] = i;
}
for (ri i = n; i; --i) {
if (h!=t&&q[h] > i + k) {
++h;
}
while (h != t && dat[i] <= dat[q[t - 1]])
--t;
q[t++] = i;
sum += dat[q[h]];
}
}
int main()
{
//freopen("d:\\yx.txt", "r", stdin);
n = read();
for (ri i = 1; i <= n; ++i) {
dat[i + n] = dat[i] = read();
}
x = read();
ll = 0; rr = n - 1;
while (ll <= rr) {
int mid = (ll + rr) >> 1;
check(sum1, mid);
check(sum2, mid + 1);
if (sum1 <= sum2) {
rr = mid - 1;
}
else
ll = mid + 1;
sum1 = min(sum1, sum2);
if (sum1 < ans)
ans = sum1;
}
printf("%lld", ans);
return 0;
}


2025-08-02 05:40:41
广告
不感兴趣
开通SVIP免广告
  • 逢部祝
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
很可惜,这个题用二分是不行的,转动总次数和花费的多少并不存在固定的单调关系,举个例子是6 [1,1,1,5,6,7] 5
不转动的最小花费是21,
转1次的最小花费是20(价格列表变成[7,1,1,1,5,6]),按照[1,1,1,1,5,6]的价格购买这些商品
(商品0,1,2在未转动的时候买,商品3,4,5在转动1次之后买)
转2次的最小花费是20(价格列表变成[6,7,1,1,1,5]),按照[1,1,1,1,1,5]的价格购买这些商品
(商品0,1,2在未转动的时候买,商品3,4,5在转动2次之后买)
转3次的最小花费是21(价格列表变成[5,6,7,1,1,1]),按照[1,1,1,1,1,1]的价格购买这些商品
(商品0,1,2在未转动的时候买,商品3,4,5在转动3次之后买)


  • 沅茝醴兰_8
  • 异能力者
    6
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
似乎感觉单调栈能够达到满分的时间复杂度,但是我在外面身边没有电脑,不能自己写一写看看对不对,就只说一说思路


  • uitstalie
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
我为什么觉得这个出题的模板看起来很眼熟?ccf?
看这个解析的描述似乎是单调栈


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 9回复贴,共1页
<<返回c语言吧
分享到:
©2025 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示