先考虑对题目进行转化,我们称两个区间有交集为这两个区间能匹配,每个询问就是在序列中最长能连续匹配的长度。

对序列中的一个区间\([l,r]\)和询问的一个区间\([L,R]\),若满足\(L \leqslant r\)且\(l \leqslant R\),那么这两个区间是能匹配的。

可以将一个区间用点来表示,然后用\(K-D\ Tree\)来维护所有的询问区间,序列区间按顺序一个个去更新每个询问的匹配信息即可。

对\(K-D\ Tree\)中的维护一个矩形来考虑,比如下图的蓝色矩形为这个矩形。

当一个点落在红色矩形时,那么该点和矩形内的所有点都能匹配,对该矩形打上加法标记,使矩形内所有点的当前匹配数加一。

当一个点落在黄色矩形时,那么该点和矩形内的所有点都不能匹配,对该矩形打上清零标记,使矩形内所有点的当前匹配数清零。

同时记录一个点在整个过程中的历史最大匹配数,其即为最终一个点所对应询问的答案。

对一个矩形清空后,还会进行一系列对其匹配数增加的操作,但此时打上加法标记是错误的,所以给它打上一个赋值标记,打标记时增加赋值标记即可,同时记录下这阶段赋值标记的历史最大值,并用其去更新该点的历史最大匹配数。

标记比较多,有很多细节,具体实现看代码吧。

\(code:\)

#include<bits/stdc++.h>
#define maxn 400010
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,m,root,tot,type;
int cov[maxn],his[maxn],add[maxn],tag[maxn];
int ans[maxn],ma[maxn],cnt[maxn];
struct node
{
int l,r;
}p[maxn];
struct KD_tree
{
int d[2],mi[2],ma[2],ls,rs,id;
}t[maxn],dat[maxn];
bool cmp(const KD_tree &a,const KD_tree &b)
{
return a.d[type]<b.d[type];
}
void pushup(int x)
{
int ls=t[x].ls,rs=t[x].rs;
for(int i=0;i<=1;++i)
{
t[x].ma[i]=t[x].mi[i]=t[x].d[i];
if(ls)
{
t[x].ma[i]=max(t[x].ma[i],t[ls].ma[i]);
t[x].mi[i]=min(t[x].mi[i],t[ls].mi[i]);
}
if(rs)
{
t[x].ma[i]=max(t[x].ma[i],t[rs].ma[i]);
t[x].mi[i]=min(t[x].mi[i],t[rs].mi[i]);
}
}
}
void update(int x,int v)
{
cnt[x]+=v,ma[x]=max(ma[x],cnt[x]);
}
void pushadd(int x,int v)
{
update(x,v);
if(cov[x]) tag[x]+=v,his[x]=max(his[x],tag[x]);
else add[x]+=v;
}
void pushcov(int x)
{
if(!cov[x]) cov[x]=1,his[x]=0;
cnt[x]=tag[x]=0;
}
void pushtag(int x,int v1,int v2)
{
cov[x]=1,his[x]=max(his[x],v2);
cnt[x]=tag[x]=v1,ma[x]=max(ma[x],his[x]);
}
void pushdown(int x)
{
int ls=t[x].ls,rs=t[x].rs;
if(add[x])
{
pushadd(ls,add[x]),pushadd(rs,add[x]);
add[x]=0;
}
if(cov[x])
{
pushtag(ls,tag[x],his[x]),pushtag(rs,tag[x],his[x]);
cov[x]=tag[x]=0;
}
}
void build(int l,int r,int k,int &x)
{
x=++tot,type=k;
int mid=(l+r)>>1;
nth_element(dat+l+1,dat+mid+1,dat+r+1,cmp);
t[x]=dat[mid];
if(l<mid) build(l,mid-1,k^1,t[x].ls);
if(r>mid) build(mid+1,r,k^1,t[x].rs);
pushup(x);
}
bool in(KD_tree tr,int l,int r)
{
return tr.ma[0]<=r&&l<=tr.mi[1];
}
bool out(KD_tree tr,int l,int r)
{
return tr.mi[0]>r||l>tr.ma[1];
}
void modify(int x,int l,int r)
{
int ls=t[x].ls,rs=t[x].rs;
if(in(t[x],l,r))
{
pushadd(x,1);
return;
}
if(out(t[x],l,r))
{
pushcov(x);
return;
}
pushdown(x);
if(t[x].d[0]<=r&&l<=t[x].d[1]) update(x,1);
else cnt[x]=0;
if(ls) modify(ls,l,r);
if(rs) modify(rs,l,r);
}
void dfs(int x)
{
int ls=t[x].ls,rs=t[x].rs;
pushdown(x),ans[t[x].id]=ma[x];
if(ls) dfs(ls);
if(rs) dfs(rs);
}
int main()
{
read(n),read(m);
for(int i=1;i<=n;++i) read(p[i].l),read(p[i].r);
for(int i=1;i<=m;++i)
read(dat[i].d[0]),read(dat[i].d[1]),dat[i].id=i;
build(1,m,0,root);
for(int i=1;i<=n;++i) modify(root,p[i].l,p[i].r);
dfs(root);
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}

题解 洛谷 P6349 【[PA2011]Kangaroos】的更多相关文章

  1. 洛谷 P6349 - [PA2011]Kangaroos(KDT+标记下放)

    洛谷题面传送门 KDT 上打标记的 hot tea. 考虑将询问 \(A,B\) 看作二维平面直角坐标系上的一个点 \((A,B)\),那么我们这样考虑,我们从左到右扫过全部 \(n\) 个区间并开一 ...

  2. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  3. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  4. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  5. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  6. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  7. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

  8. 题解-洛谷P5217 贫穷

    洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...

  9. 题解 洛谷 P2010 【回文日期】

    By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...

随机推荐

  1. 2、尚硅谷_SSM高级整合_创建Maven项目.avi

    第一步我们新建立一个web工程 这里首先要勾选上enable的第一个复选框 这里要勾选上add maven support 我们在pom.xml中添加sevlet的依赖 创建java web项目之后, ...

  2. 入门大数据---Hive常用DDL操作

    一.Database 1.1 查看数据列表 show databases; 1.2 使用数据库 USE database_name; 1.3 新建数据库 语法: CREATE (DATABASE|SC ...

  3. webpack的入门实践,看这篇就够了

    webpack的入门实践 我会将所有的读者概括为初学者,即使你可能有基础,学习本节之前我希望你具有一定的JavaScript和node基础 文中的 ... ...代表省略掉部分代码,和上面的代码相同 ...

  4. 前端基础:深入浅出 TCP/IP 协议栈

    一个主机的数据要经过哪些过程才能发送到对方的主机上 参考:https://www.cnblogs.com/onepixel/p/7092302.html 首先我们梳理一下每层模型的职责: 链路层:对0 ...

  5. git和github入门指南(3.1)

    3.远程管理 3.1.远程仓库相关命令 1.查看远程仓库名字,这里以github为例 git remote 上面命令执行后会得到:origin,这样一个名字,这个名字是我们克隆的时候默认设置好的 如果 ...

  6. 如何解决TOP-K问题

    前言:最近在开发一个功能:动态展示的订单数量排名前10的城市,这是一个典型的Top-k问题,其中k=10,也就是说找到一个集合中的前10名.实际生活中Top-K的问题非常广泛,比如:微博热搜的前100 ...

  7. (1)RabbitMQ简介与安装

    1.RabbitMQ简介 因为RabbitMQ是基于开源的AMQP协议来实现的,所以在了解MQ时候,首先我们来了解下AMQP协议.AMQP,即Advanced Message Queuing Prot ...

  8. 深度学习论文翻译解析(八):Rich feature hierarchies for accurate object detection and semantic segmentation

    论文标题:Rich feature hierarchies for accurate object detection and semantic segmentation 标题翻译:丰富的特征层次结构 ...

  9. pycharm一直显示Process finished with exit code 0

    后来排查发现原来是解释器的问题我之前使用的解释器是pycharm提供的虚拟解释器#####如何查看解释器点file–>new projects 如果选择的是2就是使用了pycharm提供的虚拟解 ...

  10. Electron + Websoket 通讯

    Electron + WebSocket + node.js 通信 描述 本文主要介绍了结合 Electron 和 node.js 进行 Websocket 通讯的一个简单例子. 项目结构 main. ...