BZOJ.1805.[IOI2007]sail船帆(贪心 线段树)
首先旗杆的顺序没有影响,答案之和在某一高度帆的总数有关。所以先把旗杆按高度排序。
设高度为\(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船帆(贪心 线段树)的更多相关文章
- BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库
正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...
- 【题解】P1712 [NOI2016]区间(贪心+线段树)
[题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...
- BZOJ1805[Ioi2007]Sail船帆——线段树+贪心
题目描述 让我们来建造一艘新的海盗船.船上有 N个旗杆,每根旗杆被分成单位长度的小节.旗杆的长度等于它被分成的小节的数目.每根旗杆上会挂一些帆,每张帆正好占据旗杆上的一个小节.在一根旗杆上的帆可以任意 ...
- BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)
BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...
- BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)
题意 这一天,\(\mathrm{Konano}\) 接到了一个任务,他需要给正在制作中的游戏 \(\mathrm{<IIIDX>}\) 安排曲目 的解锁顺序.游戏内共有\(n\) 首曲目 ...
- bzoj 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle【贪心+线段树】
按结束时间排序,然后开个线段树,按照排序后的牛群贪心的选 贪心的依据是选哪头牛都是选,不如给后面的多省一点空间 #include<iostream> #include<cstdio& ...
- bzoj 1828: [Usaco2010 Mar]balloc 农场分配【贪心+线段树】
长得挺唬人的贪心,按照右端点排序,用最小值线段树的询问判断当前牛是否能放进去,能的话更新线段树,ans++ 来自https://www.cnblogs.com/rausen/p/4529245.htm ...
- BZOJ 1828 [Usaco2010 Mar]balloc 农场分配(贪心+线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1828 [题目大意] 现在有一些线段[l,r]的需求需要满足,i位置最多允许a[i]条线 ...
- Codeforces 675E Trains and Statistic(DP + 贪心 + 线段树)
题目大概说有n(<=10W)个车站,每个车站i卖到车站i+1...a[i]的票,p[i][j]表示从车站i到车站j所需买的最少车票数,求所有的p[i][j](i<j)的和. 好难,不会写. ...
随机推荐
- WireShark Wifi认证数据包分析(论文idea)
1.使用 wireShark捕获802.11数据帧结构分成三种,管理帧.控制帧.数据帧. 使用的过滤语法: 过滤MAC 地址: Waln.bssid eq=8c:23:0c:44:21:0f 过滤特定 ...
- Linux文本分析命令awk的妙用
基本用法 awk是一个强大的文本分析工具,简单来说awk就是把文件逐行读入,(空格,制表符)为默认分隔符将每行切片,切开的部分再进行各种分析处理 awk命令格式如下 awk [-F field-sep ...
- Variable binding depth exceeds max-specpdl-size
(setq max-specpdl-size 5) ; default is 1000, reduce the backtrace level (setq debug-on-error t) ; no ...
- 集腋成裘-06-angularJS -angular_02
1.0 选项卡 其中涉及到了三目运算符号; <!DOCTYPE html> <html ng-app="test"> <head> <me ...
- Selenium+PhantomJS使用时报错原因及解决方案
问题 今天在使用selenium+PhantomJS动态抓取网页时,出现如下报错信息: UserWarning: Selenium support for PhantomJS has been dep ...
- 微信小程序--代码构成---JS 交互逻辑
一个服务仅仅只有界面展示是不够的,还需要和用户做交互:响应用户的点击.获取用户的位置等等.在小程序里边,我们就通过编写 JS 脚本文件来处理用户的操作. <view>{{ msg }}&l ...
- 20165328 预备作业3 Linux安装及命令
Linux安装及学习 Linux安装遇到的问题: 问题:在我开始安装虚拟机的时候,在安装过程中总会出现初始界面,且无法跳过,陷入死循环. 解决方法:我在网上百度搜索该问题之后得到了答案,第一个界面是要 ...
- Pycharm常用操作方法
1.调整字体大小 2.选择python编译器
- 字符转ASCII码
char k = '成'; int str = (int)k; Console.WriteLine(str); 结果25104就是‘成’对应的ASCII值
- WARN conf.FlumeConfiguration: Could not configure sink sink1 due to: No channel configured for sink: sink1 org.apache.flume.conf.ConfigurationException: No channel configured for sink: sink1
1.错误如下所示,启动flume采集文件到hdfs案例的时候,出现如下所示的错误: 大概是说No channel configured for sink,所以应该是sink哪里配置出现了错误,百度了一 ...