题目描述

让我们来建造一艘新的海盗船。船上有 N个旗杆,每根旗杆被分成单位长度的小节。旗杆的长度等于它被分成的小节的数目。每根旗杆上会挂一些帆,每张帆正好占据旗杆上的一个小节。在一根旗杆上的帆可以任意排布在不同的小节中,但是每个小节上至多能挂一张帆。 在风中,帆的不同排布方式会产生不同的推动力。靠近船头的帆比它后面的相同高度上的帆获得的推动力少,换句话说,靠近船头的帆的推动力由于受它后面相同高度的帆的影响而打了折扣。对于任意一张帆,它的推动力折扣等于在它后面并且和它在同一高度的帆的数目。 所有帆的任意一种位置组合的推动力折扣总和等于在该位置下所有帆的推动力折扣的总和。 前 后 这条船上有6个旗杆,从前(图上的左边)到后的高度分别是3,5,4,2,4和3。图中所示的帆的位置组合的总推动力折扣是10。上图给出了每张帆自己的推动力折扣。 任务 给定N个旗杆的高度和每个旗杆上挂的帆的数目,写一个程序求出所有位置组合中的可能达到的最小的总推动力折扣。

输入

第一行包含一个整数N(2 ≤ N ≤ 100 000),表示旗杆的数目。 接下来的N行每行包含两个整数H和K(1 ≤ H ≤ 100 000, 1 ≤ K ≤ H),分别表示对应旗杆的高度及其上的帆的数目。旗杆按照从船头到船尾的顺序给出。

输出

输出包含一个整数,表示可以达到的最小的总推动力折扣。 注意:计算和输出结果时使用64位整数类型(在C/C++中用long long, 在Pascal中用int64)。 评分 在25分的测试数据中,帆的不同位置组合的总数目不超过1 000 000。

样例输入

6
3 2
5 3
4 1
2 1
4 3
3 2

样例输出

10
这个样例数据和上页中图示的样例相同。
 
很有思维量的一道线段树的题。(本题有几个贪心证明统一在最后证明)
首先能发现旗杆的顺序对答案不影响(证明1),假设从下到上第i行有si个船帆,那么答案就是Σsi*(si-1)/2。
题目就可看成每次在前hi行中选ki行,使每行的si加1。
那么我们每次贪心地在前hi行中选si最小的ki行每行+1一定会使答案最优(证明2)。
如果暴力地找前ki小的每行+1显然不行,那么能不能将需要加的行变成一个区间,然后线段树上直接区间修改?
答案是可以的,我们发现对于每一步操作后的最优解中,一定有一种是满足从下到上每行船帆数单调递减的(证明3)。
这样最小的ki行就是一段区间了,但考虑修改完之后是否还保持单调递减?
假设当次修改的是[l,r],如果s[l-1]>s[l],那么修改后依旧保持单调递减。
如果s[l-1]=s[l]呢?这样修改之后s[l]就比s[l-1]大了,因此要找到最左边和s[l]相等的点L和最右边和s[l]相等的点R。
如果r<=R,即s[l]=s[r],那么就将修改区间平移到[L,L+ki-1],否则就将修改区间拆成两段:一段是[R+1,r],剩下的平移到从L开始处。
因为这样修改是尽量靠前修改的,而且旗杆顺序不影响答案,所以要将所有旗杆按长度从小到大排序。
证明1:
我们以两个旗杆a,b为例,如果b,a时的最优解比a,b时的最优解更优,那么我们将a,b调换顺序并保持b,a时船帆状态,这时的答案还是b,a时的最优解,那么之前a,b的最优解就不是最优的了。因此无论船帆是什么顺序,都不会影响答案。
证明2:
对于每一次修改,假设不选最小的那些而是将最小的留给后面,那么为了使答案最优,最小的那几个一定是要选的,先选大的再选小的也就相当于先选小的再选大的。
证明3:
假设最优解中存在i>j且si>sj,因为能放到第i行的船帆一定能放到第j行,那么一定可以将第i行比第j行多的那些都放到第j行使得si和sj大小调换且答案不变。

#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
struct miku
{
int h;
int s;
}a[100010];
int mn[800010];
int mx[800010];
int sum[800010];
int n,m;
ll ans;
bool cmp(miku a,miku b)
{
return a.h<b.h;
}
void pushup(int rt)
{
mn[rt]=min(mn[rt<<1],mn[rt<<1|1]);
mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void pushdown(int rt)
{
if(sum[rt])
{
sum[rt<<1]+=sum[rt];
sum[rt<<1|1]+=sum[rt];
mn[rt<<1]+=sum[rt];
mn[rt<<1|1]+=sum[rt];
mx[rt<<1]+=sum[rt];
mx[rt<<1|1]+=sum[rt];
sum[rt]=0;
}
}
void change(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
sum[rt]++;
mx[rt]++;
mn[rt]++;
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid)
{
change(rt<<1,l,mid,L,R);
}
if(R>mid)
{
change(rt<<1|1,mid+1,r,L,R);
}
pushup(rt);
}
int query_mid(int rt,int l,int r,int k)
{
if(l==r)
{
return mn[rt];
}
pushdown(rt);
int mid=(l+r)>>1;
if(k<=mid)
{
return query_mid(rt<<1,l,mid,k);
}
else
{
return query_mid(rt<<1|1,mid+1,r,k);
}
}
int query_left(int rt,int l,int r,int k)
{
if(l==r)
{
return l;
}
pushdown(rt);
int mid=(l+r)>>1;
if(mn[rt<<1]<=k)
{
return query_left(rt<<1,l,mid,k);
}
else
{
return query_left(rt<<1|1,mid+1,r,k);
}
}
int query_right(int rt,int l,int r,int k)
{
if(l==r)
{
return l;
}
pushdown(rt);
int mid=(l+r)>>1;
if(mx[rt<<1|1]>=k)
{
return query_right(rt<<1|1,mid+1,r,k);
}
else
{
return query_right(rt<<1,l,mid,k);
}
}
void count_ans(int rt,int l,int r)
{
if(l==r)
{
ans+=1ll*mn[rt]*(mn[rt]-1)/2;
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
count_ans(rt<<1,l,mid);
count_ans(rt<<1|1,mid+1,r);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].h,&a[i].s);
m=max(m,a[i].h);
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
int res=query_mid(1,1,m,a[i].h-a[i].s+1);
int L=query_left(1,1,m,res);
int R=query_right(1,1,m,res);
if(R<a[i].h)
{
int len=a[i].h-R;
change(1,1,m,R+1,a[i].h);
change(1,1,m,L,L+(a[i].s-len)-1);
}
else
{
change(1,1,m,L,L+a[i].s-1);
}
}
count_ans(1,1,m);
printf("%lld",ans);
}

BZOJ1805[Ioi2007]Sail船帆——线段树+贪心的更多相关文章

  1. bzoj1805: [Ioi2007]Sail 船帆

    可以发现旗杆的顺序是没有用的,对于每列,它的答案是它的最大值mx*(mx+1)/2 高度由小到大排序旗杆,问题可以转化为在前h行选k个最小的值 考虑激情splay乱搞(我只会splay......) ...

  2. BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...

  3. Bzoj5251 线段树+贪心

    Bzoj5251 线段树+贪心 记录本蒟蒻省选后的第一篇题解!国际惯例的题面:首先这个东西显然是一棵树.如果我们把数值排序,并建立这棵树的dfs序,显然dfs序上的一个区间对应数值的一个区间,且根为数 ...

  4. 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)

    传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码

  5. BZOJ.1805.[IOI2007]sail船帆(贪心 线段树)

    BZOJ 洛谷 首先旗杆的顺序没有影响,答案之和在某一高度帆的总数有关.所以先把旗杆按高度排序. 设高度为\(i\)的帆有\(s_i\)个,那么答案是\(\sum\frac{s_i(s_i-1)}{2 ...

  6. codeforces 675E Trains and Statistic 线段树+贪心统计

    分析:这个题刚看起来无从下手 但是我们可以先简化问题,首先可以固定起点i,求出i+1到n的最小距离 它可以到达的范围是[i+1,a[i]],贪心的想,我们希望换一次车可以到达的距离尽量远 即:找一个k ...

  7. BZOJ5249 九省联考2018IIIDX(线段树+贪心)

    显然这形成了一个树形结构.考虑这样一种贪心:按照曲目顺序,每次取消其父亲的预留,并选择当前可选择(保证其子树有合法选择且满足预留)的最大值,然后对其子树预留出大于等于他的一些值.这个做法显然是正确的. ...

  8. BZOJ5249: [2018多省省队联测]IIIDX(线段树 贪心)

    题意 题目链接 Sol 不难发现题目给出的是一个树,其中\(\frac{i}{K}\)是\(i\)的父亲节点 首先,当\(d_i\)互不相同时,一个显然的贪心策略就是优先给编号小的分配较大的权值.可以 ...

  9. [九省联考2018] IIIDX 线段树+贪心

    题目: 给出 k 和 n 个数,构造一个序列使得 d[i]>=d[i/k] ,并且字典序最大. 分析: 听说,当年省选的时候,这道题挡住了大批的高手,看上去十分简单,实际上那道弯段时间内是转不过 ...

随机推荐

  1. FreeRTOS的任务非运行态

    当FreeRTOS启动任务调度器以后,任务调度器会在心跳中断函数中确定下一个要运行的任务,如果任务调度器仅仅依靠任务优先级来判断该运行哪个任务,这样会造成低优先级的任务根本没法运行,因为FreeRTO ...

  2. Android 让图片等比例缩放的三种方法

    方法一:客户端等比例 前提条件:服务器端需要返回原始图片的“宽和高”或者“宽高缩放比例”,客户端要显示的图片的宽或者高只要其一是固定的(例如:高度为200,宽度未知,或者高度为400宽度未知) 在这种 ...

  3. 开放的dae模型

    从网上看到了这段代码,就Copy过来了. 其实面对dae这种开放的模型格式,我们可以做很多事情,就像通常的XML文件一样. //------------------------------------ ...

  4. 解析 STM32 的库函数

    解析 STM32 的库函数意法半导体在推出 STM32 微控制器之初,也同时提供了一套完整细致的固件开发包,里面包含了在 STM32 开发过程中所涉及到的所有底层操作.通过在程序开发中引入这样的固件开 ...

  5. Sharding模式

    将数据存储为一组水平的数据分区.这种模式可以在存储和访问大量的数据的时候提高可扩展性. 场景和问题 由单个服务器托管的数据存储可能受到下列限制: 存储空间限制.基于大规模云应用所使用的数据仓库,可能会 ...

  6. 洛谷 P4409 [ZJOI2006] 皇帝的烦恼

    题目链接-> OVO 题解: 很久没有写博客了,可能是因为最近太颓废了吧. 刚刚考完期末考试,无比期盼早点外出学习,不要面对成绩,害怕. #include <cstdio> #inc ...

  7. 你要的fpga&数字前端笔面试题都在这儿了

    转自http://ninghechuan.com 你要的FPGA&数字前端笔面试题来了 FPGA&ASIC基本开发流程 题目:简述ASIC设计流程,并列举出各部分用到的工具. 勘误:C ...

  8. 学习ML.NET(3): 导入数据集

    机器学习算法需要作用于数据,用来训练算法模型.数据集通常是以纯文本文件存储的表格数据,文件的每一行是一条数据记录,每条记录由多列组成,列之间用分隔符(一般是逗号,)分开,例如前面用到过的鸢尾花数据集. ...

  9. PHP从入门到精通(二)

     PHP从入门到精通 之PHP中的函数 各位开发者朋友大家好,自上次更新PHP的相关知识,得到了大家的广泛支持.PHP的火爆程度不言而喻,函数作为PHP中极为重要的部分,应诸位的支持,博主继续跟进更新 ...

  10. Linux内核分析作业六

    1.阅读理解task_struct数据结构 2.分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构: fork进程的代码 #inclu ...