BZOJ

洛谷


首先旗杆的顺序没有影响,答案之和在某一高度帆的总数有关。所以先把旗杆按高度排序。

设高度为\(i\)的帆有\(s_i\)个,那么答案是\(\sum\frac{s_i(s_i-1)}{2}\),显然我们要让每一行(高度)的帆数都尽量少。

然后可以想到二分,二分每一行的帆数不超过\(mid\)是否可行。显然我们从最高的旗杆的最大高度部分往下填就可以了,要用线段树维护。复杂度\(O(n\log^2n)\)。

但是不需要这个二分啊,每次找到\(s_i\)最小的位置,把\(k\)个帆填进去就行了。

那么显然把旗杆从低到高排序,每次覆盖\(s_i\)最小的区间,就可以保证正确性了。

线段树维护,把这\(k\)个位置填到\([h-k+1,h]\)。这个区间的左端点可能不是一段完整的连续值域区间的左端点,需要将在该一部分平移到该连续段左端点去覆盖来保证\(s_i\)递减。对此就找到\(h-k+1\)位置处连续段的左右端点\(L,R\),判一下\(R\)是否\(<h\)就好了。(画个图很容易理解,初始时就可能是这样的)

复杂度\(O(n\log n)\)。


可以用树状数组写,虽然查询位置是两个\(\log\)的,但是常数太小了没O2线段树比不过。

//5028kb	1036ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define mp std::make_pair
#define pr std::pair<int,int>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5; pr A[N];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define S N<<2
int mn[S],tag[S];
#undef S
#define Upd(rt,v) mn[rt]+=v,tag[rt]+=v
#define Update(rt) mn[rt]=std::min(mn[ls],mn[rs])
#define PushDown(rt) Upd(ls,tag[rt]), Upd(rs,tag[rt]), tag[rt]=0
void Modify(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) {Upd(rt,1); return;}
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
if(L<=m) Modify(lson,L,R);
if(m<R) Modify(rson,L,R);
Update(rt);
}
int FindPos(int l,int r,int rt,int p)
{
while(l!=r)
{
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
p<=m ? (r=m,rt=ls) : (l=m+1,rt=rs);
}
return mn[rt];
}
int FindL(int l,int r,int rt,int val)
{
while(l!=r)
{
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
mn[ls]<=val ? (r=m,rt=ls) : (l=m+1,rt=rs);
}
return l;
}
int FindR(int l,int r,int rt,int val)
{
while(l!=r)
{
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
mn[ls]<val ? (r=m,rt=ls) : (l=m+1,rt=rs);
}
return mn[rt]==val?l:l-1;
}
LL Calc(int l,int r,int rt)
{
if(l==r) return 1ll*mn[rt]*(mn[rt]-1)>>1;
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
return Calc(lson)+Calc(rson);
}
}T; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
} int main()
{
#define S 1,lim,1
const int n=read();
for(int i=1,h; i<=n; ++i) h=read(),A[i]=std::make_pair(h,read());//h,k
std::sort(A+1,A+1+n);
int lim=A[n].first;
for(int i=1; i<=n; ++i)
{
int h=A[i].first,k=A[i].second;
int mn=T.FindPos(S,h-k+1),L=T.FindL(S,mn),R=std::min(h,T.FindR(S,mn));
if(L!=h-k+1)//if(R<h)
{
T.Modify(S,L,L+k-h+R-1);
if(R<h) T.Modify(S,R+1,h);
}
else T.Modify(S,L,L+k-1);
}
printf("%lld\n",T.Calc(S)); return 0;
}

BZOJ.1805.[IOI2007]sail船帆(贪心 线段树)的更多相关文章

  1. BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库

    正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...

  2. 【题解】P1712 [NOI2016]区间(贪心+线段树)

    [题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...

  3. BZOJ1805[Ioi2007]Sail船帆——线段树+贪心

    题目描述 让我们来建造一艘新的海盗船.船上有 N个旗杆,每根旗杆被分成单位长度的小节.旗杆的长度等于它被分成的小节的数目.每根旗杆上会挂一些帆,每张帆正好占据旗杆上的一个小节.在一根旗杆上的帆可以任意 ...

  4. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  5. BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)

    题意 这一天,\(\mathrm{Konano}\) 接到了一个任务,他需要给正在制作中的游戏 \(\mathrm{<IIIDX>}\) 安排曲目 的解锁顺序.游戏内共有\(n\) 首曲目 ...

  6. bzoj 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle【贪心+线段树】

    按结束时间排序,然后开个线段树,按照排序后的牛群贪心的选 贪心的依据是选哪头牛都是选,不如给后面的多省一点空间 #include<iostream> #include<cstdio& ...

  7. bzoj 1828: [Usaco2010 Mar]balloc 农场分配【贪心+线段树】

    长得挺唬人的贪心,按照右端点排序,用最小值线段树的询问判断当前牛是否能放进去,能的话更新线段树,ans++ 来自https://www.cnblogs.com/rausen/p/4529245.htm ...

  8. BZOJ 1828 [Usaco2010 Mar]balloc 农场分配(贪心+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1828 [题目大意] 现在有一些线段[l,r]的需求需要满足,i位置最多允许a[i]条线 ...

  9. Codeforces 675E Trains and Statistic(DP + 贪心 + 线段树)

    题目大概说有n(<=10W)个车站,每个车站i卖到车站i+1...a[i]的票,p[i][j]表示从车站i到车站j所需买的最少车票数,求所有的p[i][j](i<j)的和. 好难,不会写. ...

随机推荐

  1. Unity3D料槽设备旋转(一)

    1.使用C#创建控制游戏对象的的脚本语言, 第一步: 在project师徒中create 一个C#脚本,将其按照自己的设备名称进行命名,这里我将其简单的命名成zhuaquanzhou.cs 使用编辑器 ...

  2. Android Studio 调用夜神模拟器

    操作系统:Windows 10 x64 IDE:Android Studio 3.3 夜神模拟器 首先,启动夜神模拟器.快捷键WIN + R打开运行窗口,输入cmd,启动cmd.exe. 使用cd命令 ...

  3. linux把程序做成系统服务并自启动

    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 一.chkconfig 的使用语法1.c ...

  4. Navicat Premium 12.1.8.0安装与激活

    本文介绍Navicat Premium 12.1.8.0的安装.激活与基本使用. 博主所提供的激活文件理论支持Navicat Premium 12.0.x系列和Navicat Premium 12.1 ...

  5. 使用heptiolabs/eventrouter收集K8S的事件

    k8s的heapster项目中止以后, 事件收集的项目,就推荐使用https://github.com/heptiolabs/eventrouter项目了. 部署文档很简单,但有两个问题要解决: 一, ...

  6. nginx的with-http_sub_module模块使用之替换字符串

    一.介绍 该ngx_http_sub_module模块是一个过滤器,通过将一个指定的字符串替换为另一个字符串来修改响应.该模块不是默认生成的,它应该使用--with-http_sub_module 配 ...

  7. 【ASP.NET】UCenter实现多站点同步注册

    问题描述 上一篇文章写了[ASP.Net]UCenter实现多站点同步登录退出 在整合论坛的时候,同步注册也是相当必要的一个功能:将论坛注册的用户同步到自己的网站,自己网站注册的用户同步到论坛. 官方 ...

  8. jQuery懒加载插件 – jquery.lazyload.js简单调用

    Lazy Load 是一个用 JavaScript 编写的 jQuery 插件. 它可以延迟加载长页面中的图片. 在浏览器可视区域外的图片不会被载入, 直到用户将页面滚动到它们所在的位置. 这与图片预 ...

  9. 给linux服务器添加一块新的磁盘

    http://www.linuxidc.com/Linux/2011-02/31868.htm 把硬盘装好后,我们用 fdisk -l 查看下: 图中可以看出 /dev/sdb 是500G,新加的硬盘 ...

  10. 012 pandas与matplotlib结合制图

    这里以后再补充. 1.折线图