题目传送门(内部题89)


输入格式

第一行两个数$n$和$k$,分别表示小鸟的只数和$R$装弹时间。
接下来$n$行,每行两个数$l,r$表示$n$只小鸟初始时的头和尾的$x$坐标。


输出格式

输出一个答案表示$R$最多能得到多少只猎物。


样例

样例输入:

4 5
-1 1
2 4
5 9
6 8

样例输出:

3


数据范围与提示

对于$30\%$的数据:$n\leqslant 20,\max(|l|,|r|)\leqslant 100$。
对于$60\%$的数据:$n\leqslant 5,000,\max(|l|,|r|)\leqslant 5,000$。
对于$100\%$的数据:$n\leqslant 100,000,\max(|l|,|r|)\leqslant 500,000$。


题解

注意两次开枪之间的间隔只需要在$k$之上就好了,不需要一定是$k$。

状态转移很好写,在此不再赘述,用线段树优化即可满分。

但是需要注意的是,如果一直鸟的长度$>k$,那么就会被计数两次,若和避免这样的情况呢?

用一个数组记录当前点的鸟有多少,再在这只鸟飞走的时候再将其插入线段树,而当前点的答案就是线段树里能覆盖这个点的鸟$+$维护的那个数组的当前点的值。

因为在鸟飞走后再将其插入,所以就避免了重复计算。

注意边界问题,即$l,r<0$的情况;具体实现可以参考代码。

时间复杂度:$\Theta(n\log \max(|l|,|r|))$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
struct rec{int l,r;}pos[100001];
int n,k;
int s[500002],beg[500002],mx;
int tr[2000010],lz[2000010];
int ans;
bool cmp(rec a,rec b){return a.r==b.r?a.l<b.l:a.r<b.r;}
void pushup(int x){tr[x]=max(tr[L(x)],tr[R(x)]);}
void pushdown(int x){tr[L(x)]+=lz[x];lz[L(x)]+=lz[x];tr[R(x)]+=lz[x];lz[R(x)]+=lz[x];lz[x]=0;}
void add(int x,int l,int r,int k,int w)
{
if(l==r){tr[x]=w;return;}
int mid=(l+r)>>1;
pushdown(x);
if(k<=mid)add(L(x),l,mid,k,w);
else add(R(x),mid+1,r,k,w);
pushup(x);
}
void add(int x,int l,int r,int L,int R,int w)
{
if(r<L||R<l)return;
if(L<=l&&r<=R){tr[x]+=w;lz[x]+=w;return;}
int mid=(l+r)>>1;
pushdown(x);
add(L(x),l,mid,L,R,w);
add(R(x),mid+1,r,L,R,w);
pushup(x);
}
int ask(int x,int l,int r,int L,int R)
{
if(r<L||R<l)return 0;
if(L<=l&&r<=R)return tr[x];
int mid=(l+r)>>1;
pushdown(x);
return max(ask(L(x),l,mid,L,R),ask(R(x),mid+1,r,L,R));
}
int main()
{
scanf("%d%d",&n,&k);
int top=0;
for(int i=1;i<=n;i++)
{
int l,r;
scanf("%d%d",&l,&r);
l=max(l,0);if(r<0)continue;
l++;r++;s[l]++;s[r+1]--;
pos[++top]=(rec){l,r};
beg[l]++;mx=max(mx,r+1);
}
n=top;sort(pos+1,pos+n+1,cmp);
for(int i=1;i<=mx;i++)s[i]+=s[i-1];
int fail=1,now=0;
for(int i=1;i<=mx;i++)
{
int flag=s[i]+ask(1,1,mx,max(0,i-(k<<1)),max(0,i-k));
now+=beg[i];ans=max(ans,flag);
add(1,1,mx,i,flag-now);
while(fail<=n&&pos[fail].r==i)
{
now--;
add(1,1,mx,pos[fail].l,pos[fail].r,1);
fail++;
}
}
printf("%d",ans);
return 0;
}

rp++

最新文章

  1. ResultSet 结果集带回来的一些信息
  2. 常用的7个.htaccess代码组织某个国家的IP访问
  3. 查看LINUX进程内存占用情况
  4. SSH原理与运用(二):远程操作与端口转发
  5. 获取设备唯一标识 uuid(采用第三方库SSKeychain)
  6. (实用篇)php中计算中文字符串长度、截取中文字符串的函数代码
  7. 从SQL Server中导入/导出Excel的基本方法(转)
  8. Android:实现数组之间的复制
  9. Linkedin工程师是如何优化他们的Java代码的(转)
  10. Java基础(1) - 语法 &amp; 概念
  11. JavaScript基础知识(概念、常量和变量)
  12. POJ - 3984迷宫问题(最短路径输出)
  13. 『TensorFlow』使用集合collection控制variables
  14. Fedora 21 安装 Bumblebee with the NVIDIA proprietary drivers
  15. vue生命周期 钩子函数
  16. dp之二维背包hdu3496
  17. layDay日期格式不合法报错解决
  18. linux解压分卷压缩的zip文件
  19. Helix Server流媒体服务器架设教程(附Helix Server11.01下载)
  20. 如何使用python查看视频的长度

热门文章

  1. Vue.js官方文档学习笔记(二)组件化应用的构建
  2. CF 631B 题解
  3. 滑雪(dp或记忆化搜索)
  4. git diff 命令用法
  5. CSP-S全国模拟赛第四场 【nan?】
  6. ELK-6.5.3学习笔记–elk基础环境安装
  7. maven配置生成可执行的jar:maven-shade-plugin
  8. springboot项目抓数据后优化配置及四个补充
  9. IE6兼容笔记
  10. jenkins 构建时显示git分支插件、显示构建分支插件