codeforces 99999/553 Sultan's Pearls Solution 珍珠 题解
珍珠
题意
一共n课珍珠,m颗悬挂,其余在桌子上。如图所示。
仆人每天从某一端“借”一颗珍珠珠。主人每天都会检查悬挂的珍珠数目。

每颗珍珠的摩擦系数都是kkk.
若有wh>kwtw_h \gt kw_twh>kwt,则珍珠落地,被主人发现。
珍珠iii的质量是wiw_iwi,价格是cic_ici.
问仆人最大可以借多少价钱的珍珠,并输出借的珍珠数目和一种“借”的方案。
分析
增加限定条件
如果我们增加题目的限定条件,不允许从悬挂端取珍珠。显然,从左边能取的最大珍珠数有一个限度。并且符合单调性。即,如果可以取aaa颗,则一定可以取b(b<a)b(b<a)b(b<a)颗;如果取aaa颗不行,则取b(b>a)b(b>a)b(b>a)一定不行。故可以二分。
当然,如果只是如此的话,直接枚举比二分划算,因为每次求wtw_twt的代价是线性的,除非预先线性求出前缀和,之后可以Θ(1)\Theta(1)Θ(1).
去掉限定条件
现在假设我们通过一系列合法的操作已经去掉了若干颗悬挂端末尾的珍珠,达到了末尾珠子是endendend号的状态。然后加上上面所述的限定条件,则在这种状态下的最优情况由以上可知可以二分求得。
如此来看,我们还需要解决的问题有:
- 状态仅由结尾珠子是endendend表示知否足够?即如此做是否考虑了所有情况?
- 如何确定状态是否可由合法操作得到。
对于1,事实是足够的。endendend确定了,悬挂的珠子就确定了,即whw_hwh确定了,那么能躺在桌子上的最后的极限情况就是不变的。因为每颗珠子质量非负,因此在这个状态是可达的情况下,在达到这个状态之前去除左边的还是达到之后去除从效果上来看没有差异。因此结尾为endendend,开头只需要设置为1号即考虑了所有情况。
对于2,因为珠子质量非负,可以肯定的是左边桌子端一颗不能少。因为不可能这么存在一种情况。
两种情况S1,S2S_1,S_2S1,S2的珠子,除了S1S_1S1比S2S_2S2左边少了几颗,剩余的从右边看都是一样的。而S1S_1S1经过一番合法操作可以到达末尾为endendend号珠子的状态,而S2S_2S2却无法到达。事实上,如果S1S_1S1可以,只要S2S_2S2抄S1S_1S1的操作就一定可以。
知道了以上这点,显然我们的操作就无需选择了,只剩下不断的取下珠子,直到结尾是endendend即可。然后需要保证每一步取完都是不会落地的。因此,从后往前枚举end,尝试取就好。
Code
#include <bits/stdc++.h>
using namespace std;
class Sum
{
private:
vector<int> sum;
public:
Sum()
{
}
void set(vector<int> &val)
{
sum.clear();
if (val.empty())
return;
sum.push_back(val[0]);
int sz = val.size();
for (int i = 1; i < sz; ++i)
sum.push_back(sum[i - 1] + val[i]);
}
inline int get_sum(int i)
{
return i >= 0 ? sum[min<int>(i, sum.size())] : 0;
}
// sum[l..r]
inline int get_sum(int l, int r)
{
return get_sum(r) - get_sum(l - 1);
}
void print()
{
for (auto x : sum)
cout << x << " ";
cout << endl;
}
};
class Pearls
{
private:
int total_cnt;
int hang_cnt;
int k;
vector<int> weight;
vector<int> cost;
Sum w;
Sum c;
struct Ans
{
int l;
int r;
int cost;
bool valid;
void update(int l0, int r0, int cost0)
{
if (valid)
{
if (cost0 > cost)
{
l = l0;
r = r0;
cost = cost0;
}
}
else
{
l = l0;
r = r0;
cost = cost0;
valid = true;
}
}
void print()
{
cout << l + r << " " << cost << endl;
string s(r,'H');
string ss(l,'T');
cout<<s<<ss<<endl;
}
}ans;
public:
void init()
{
cin >> total_cnt >> hang_cnt >> k;
weight.resize(total_cnt + 1);
cost.resize(total_cnt + 1);
weight[0] = cost[0] = 0;
for (int i = 1; i <= total_cnt; ++i)
{
cin >> weight[i] >> cost[i];
}
w.set(weight);
c.set(cost);
}
void work()
{
int w_h;
int w_t;
int table_end;
for (int end = total_cnt; end >= hang_cnt; --end)
{
table_end = end - hang_cnt;
w_h = w.get_sum(table_end + 1, end);
w_t = w.get_sum(1, table_end);
if (w_h > k * w_t)
{
// 前面一颗珠子不少仍旧无法实现这个状态的平衡,则无法实现。
// 因为end更小的无法绕过这一end的状况。所以更小的end也无需考虑。
break;
}
int l = 1; // is ok 可以维持平衡
int r = table_end + 1; // is not ok 不可以维持平衡
while (r - l > 1)
{
int m = l + (r - l) / 2;
w_t = w.get_sum(m, table_end);
if (w_h <= k * w_t)
{ // m is ok
l = m;
}
else
{
r = m;
}
}
ans.update(l-1, total_cnt - end, c.get_sum(1, l - 1) + c.get_sum(end + 1, total_cnt));
}
ans.print();
}
};
int main()
{
Pearls *p = new Pearls();
p->init();
p->work();
delete p;
return 0;
}
codeforces 99999/553 Sultan's Pearls Solution 珍珠 题解的更多相关文章
- Codeforces Round #609 (Div. 2)前五题题解
Codeforces Round #609 (Div. 2)前五题题解 补题补题…… C题写挂了好几个次,最后一题看了好久题解才懂……我太迟钝了…… 然后因为longlong调了半个小时…… A.Eq ...
- Codeforces Round #553 (Div. 2) C
C. Problem for Nazar time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Codeforces Round #553 (Div. 2) D题
题目网址:http://codeforces.com/contest/1151/problem/D 题目大意:给出n组数对,(ai , bi),调整这n组数对的位置,最小化 ∑(ai*( i -1)+ ...
- Codeforces Round #553 (Div. 2) C题
题目网址:http://codeforces.com/contest/1151/problem/C 题目大意:给定奇数集和偶数集,现构造一个数组,先取奇数集中一个元素1,再取偶数集二个元素2,4,再取 ...
- Codeforces Round #553 (Div. 2) B题
题目网址:http://codeforces.com/contest/1151/problem/B 题目大意:给定一个n*m的矩阵,问是否可以从每一行中选择一个数,使得这n个数异或大于0,如果可以还要 ...
- Codeforces Round #553 (Div. 2) A题
题目网址:http://codeforces.com/contest/1151/problem/A 题目大意:给定一个由大写字母构成的字符串和它的长度,有这样的操作,使任意一个字母变成与其相邻的字母, ...
- Codeforces Round #553 (Div. 2) E 贡献
https://codeforces.com/contest/1151/problem/E 题意 一条长n的链,每个点上有值\(a[i]\),定义\(f(l,r)\)为该区间的\(值\)所代表的点留下 ...
- Codeforces Round #553 (Div. 2) C 等差数列求和 + 前缀和
https://codeforces.com/contest/1151/problem/C 题意 有两个等差数列(1,3,5,..),(2,4,6,...),两个数列轮流取1,2,4,...,\(2^ ...
- Codeforces Round #551 (Div. 2) EF Solution
E. Serval and Snake 对于一个矩形,如果蛇的一条边与它相交,就意味着这条蛇从矩形内穿到矩形外,或者从矩形外穿到矩形内.所以如果某个矩形的答案为偶数,意味着蛇的头尾在矩形的同一侧(内或 ...
随机推荐
- [Python]pip 国内源
临时使用方法 pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com celery END
- webpack性能优化
Webpack优化打包速度以及性能优化 1.跟上技术的迭代(Node.Npm.Yarn) 2.在尽可能少的模块上应用loader 3.Plugin尽可能精简并确保可靠 4.resolve参数合理配置 ...
- KVM管理工具webvirtmgr的使用
WebVirtMgr的日常配置:添加宿主机,创建虚拟机,磁盘扩容,快照等具体操作记录如下: 一.创建虚拟机 1.创建存储池 点击创建的宿主机,进入虚拟机部署界面 点击“存储池”按钮,创建存储池(即创建 ...
- xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 2.登录的实现
第二章登录的实现 金庸<倚天屠龙记> 张三丰缓缓摇头,说道:“少林派累积千年,方得达成这等绝技,决非一蹴而至,就算是绝顶聪明之人,也无法自创.”他顿了一顿,又道:“我当年在少林寺中住过,只 ...
- JavaWeb学习(四) : JSP 基本语法
引入 JSP 的概念: 通俗来讲 : 在 HTML 代码中混合 Java 代码能让网页具有动态的功能, 而嵌入了 Java 代码的网页就是 JSP. JSP 的特点(优点) : 1.运行于服务端(是一 ...
- bootstrap-table.js 自适应窗体设置
$(window).resize(function () { $('#dtOrder').bootstrapTable('resetView') })
- 从零开始一个个人博客 by asp.net core and angular(一)
这是一个个人叙述自己建设博客的帖子,既然是第一篇那肯定是不牵扯代码了,主要讲一下大体的东西,微软最新的web框架应该就数asp.net core 3.1了这是一个长期支持版,而且是跨平台又开源版本,所 ...
- 10.python内置模块之os模块
os模块的作用:os 模块提供了非常丰富的方法用来处理文件和目录(管理和维护目录以及文件). os.path模块的作用:主要用于获取文件的属性(管理路径的(物理地址)). 小生总结了一些平时常用到的属 ...
- The Ether 靶场
0x01 首先对靶场进行端口扫描 发现只开启了80端口和22端口 0x02 目录扫描 访问了几个目录并没有什么发现 0x03 访问主页几个网站链接 发现了一个疑似文件包含的漏洞 0x04 抓包进行分析 ...
- [APIO2018] New Home 新家 [线段树,multiset]
线段树的每个点表示当前点的前驱,即这个颜色上一次出现的位置,这个玩意multiset随便写写就完了. 重要的是怎么查询答案,无解显然先判掉. 线段树上二分就可以了 #include <bits/ ...