Link:

BZOJ 1805 传送门

Solution:

一道思路比较巧的线段树的题目

首先可以发现,答案和顺序是没有关系的,都是$\sum_{i=1}^n {H_i∗(H_i−1)/2}$。

那么可以比较容易得得到以下的贪心策略:

对于第$i$个船帆,对前$H_i$层中的前$K_i$小的数加1

感性证明:最优方案肯定是每层上数量尽量接近,那么每次放在当前数量最少的层上一定不会使答案变差

此题的难点还是在实现上,

为了对于每个$i$都能区间+1,序列一定要具有单调性

又由于$H_i$是从小到大排序的,每次区间加时注意维护序列从大到小递减即可

但每次对$[H_i-K_i+1,H_i]$+1是不一定能保证单调的,

于是我们找到$seg[H_i-K_i+1]$第一个出现的位置$posr$和结束的位置$posl$,

由于$seg[posl]$更小,我们先尽量选取$[posl,H_i]$,再从$posr$开始选取从而保证单调性

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int,int> P;
#define mid ((l+r)>>1)
#define lc k<<1,l,mid
#define rc k<<1|1,mid+1,r
#define F first
#define S second const int MAXN=1e5+;
const int INF=<<;
int n,maxk=;
ll res=;
P dat[MAXN]; int seg[MAXN<<],tag[MAXN<<]; void push_up(int k){seg[k]=min(seg[k<<],seg[k<<|]);}
void push_down(int k)
{
if(!tag[k]) return;
seg[k<<]+=tag[k];seg[k<<|]+=tag[k];
tag[k<<]+=tag[k];tag[k<<|]+=tag[k];
tag[k]=;
} void build(int k,int l,int r)
{
if(l==r)
{
if(l==maxk) seg[k]=-INF; //要增加最后一位!
else seg[k]=;
return;
}
build(lc);build(rc);
push_up(k);
} int find_val(int x,int k,int l,int r)
{
if(l==r) return seg[k];
push_down(k);
if(x<=mid) return find_val(x,lc);
else return find_val(x,rc);
} int find_pos(int x,int k,int l,int r)
{
if(l==r) return l;
push_down(k);
if(seg[k<<]<=x) return find_pos(x,lc);
else return find_pos(x,rc);
} void Update(int a,int b,int k,int l,int r)
{
if(a<=l && r<=b)
{
seg[k]++;tag[k]++;
return;
}
push_down(k);
if(a<=mid) Update(a,b,lc);
if(b>mid) Update(a,b,rc);
push_up(k);
} void cnt(int k,int l,int r)
{
if(l==maxk) return;
if(l==r)
{
res+=1ll*seg[k]*(seg[k]-)/;
return;
}
push_down(k);
cnt(lc);cnt(rc);
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",&dat[i].F,&dat[i].S),maxk=max(maxk,dat[i].F);
sort(dat+,dat+n+);maxk++;
build(,,maxk); for(int i=;i<=n;i++)
{
int num=find_val(dat[i].F-dat[i].S+,,,maxk); //当前位置
int posl=find_pos(num-,,,maxk); //第一个小于num的的数的位置
int posr=find_pos(num,,,maxk); //第一个等于num的数的位置 if(posl<=dat[i].F) Update(posl,dat[i].F,,,maxk);
Update(posr,posr+min(dat[i].S,posl-(dat[i].F-dat[i].S+))-,,,maxk);
} cnt(,,maxk);
printf("%lld",res);
return ;
}

Review:

1、如果序列单调,则可用线段树查询的方式找出第一个小于/大于/等于$x$的数

2、对边界问题还是要敏感些啊,

此题中如果不添加最后一位,并将$seg[maxk]=-INF$,则可能出现$posl=(dat[i].F-dat[i].S+1)$,导致溢出

3、算是又了解了一种在线段树上维护单调性的方法吧,

要先找到这个数第一个出现的位置$pos$,再从$pos$开始操作即可

[BZOJ 1805] Sail 船帆的更多相关文章

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

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

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

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

  3. bzoj1805: [Ioi2007]Sail 船帆

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

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. bzoj月赛1805

    题目在最后,FG还不会做,等着$NicoDafaGood$和$Achen$给我讲 A 对于每一个质因子建一棵线段树,直接查询就好了 主要是看到所有数的大小都不是很大,然后质因子最多只有log个,复杂度 ...

  6. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  7. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  8. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  9. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

随机推荐

  1. HDU2389:Rain on your Parade(二分图最大匹配+HK算法)

    Rain on your Parade Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 655350/165535 K (Java/Ot ...

  2. SpringMVC学习 -- ModelAndView , Model , ModelMap , Map 及 @SessionAttributes 的使用

    输出模型数据: ModelAndView:处理方法返回值类型为 ModelAndView 时 , 其中包含视图和模型信息.方法体即可通过该对象添加模型数据 , 即 SpringMVC 会把 Model ...

  3. webpack 的第三方库分离并持久化缓存

    我们常常需要在浏览器缓存一些稳定的资源,如第三方库等.要达到这个目标,只需要两步: 1.提取出“稳定的资源”: 2.提供稳定的文件hash . 处理后的出的文件就像这样子: app.1w3ad4q4. ...

  4. eclipse 4.2生成wsdl 客户端

    eclipse版本 4.2  64位  ,jdk 1.6   64位 Eclipse Java EE IDE for Web Developers. Version: Juno Service Rel ...

  5. C#三层中的分页

    最近写了一个winform的管理系统,里面的分页同学推荐了几种,感觉都不好用,比较麻烦,自己就找了一个比较简单的分页,利用数据存储过程来分页. reate proc usp_User@pageInde ...

  6. BZOJ 4514: [Sdoi2016]数字配对

    4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1606  Solved: 608[Submit][Statu ...

  7. bzoj 1050: [HAOI2006]旅行comf&&【codevs1001】

    Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求 一条路径,使得路径上最 ...

  8. Codeforces Round #301 解题报告

    感觉这次的题目顺序很不合理啊... A. Combination Lock   Scrooge McDuck keeps his most treasured savings in a home sa ...

  9. mysqli_insert_id

    mysqli_insert_id($mysqli),这个函数一开始我用的时候老是返回0,疯掉了,百度了n次,问了n个人,搞了几天,就是解决不了,最后我把他换成面对对象编程,终于成功了,开心,也许这就是 ...

  10. HTML5之FileReader的简易使用

    用来把文件读入内存,并且读取文件中的数据.FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据.FileReader接口提供了读取文件的方法 ...