洛谷 P6349 - [PA2011]Kangaroos(KDT+标记下放)
KDT 上打标记的 hot tea。
考虑将询问 \(A,B\) 看作二维平面直角坐标系上的一个点 \((A,B)\),那么我们这样考虑,我们从左到右扫过全部 \(n\) 个区间并开一个变量 \(cnt\) 表示当前与 \([l_i,r_i]\) 有交的区间的最大长度,如果当前扫描到的区间 \([l_i,r_i]\) 与区间 \([A,B]\) 有交,那么我们就令 \(cnt\) 加 \(1\),否则 \(cnt\) 清空,答案就是任意时刻最大的 \(cnt\)。
显然如果我们暴力地对所有区间都重复一遍这个操作那时间复杂度肯定爆炸,考虑如何优化,我们将所有询问离线下来并一遍扫过全部 \(n\) 个区间处理所有询问,不难发现对于一个区间 \([l_i,r_i]\) 而言,与其没有交的询问对应的点肯定会落在两个矩形内,因此我们每次需要做的即是:
- 将某两个矩形中所有点的权值清零。
- 将不在这两个矩形中的所有点权值加一
最后要求的即是每个节点权值的历史最大值。
考虑对这 \(m\) 个询问点建立 KDT,那么根据 KDT 那一套理论,我们可以将矩形上的操作转化为 \(\sqrt{n}\) 个单点操作 \(+\) \(\sqrt{n}\) 个子树操作。单点操作是容易的,难点在于子树操作,因此我们现在要实现的即为:
- 将子树内所有点权值清零
- 将子树内所有点权值加一
对求解历史最大值线段树比较了解的同学到这一步应该会做了。但是我对理是最大值线段树不是太了解,因此这里会较为详细地讲解一下如何用历史最大值的标记解决这个问题。我们考察一个点上一次标记下推到现在一共经历了哪些过程,有两种可能,要么没有被清空,权值直接被加上了一个数 \(v\)。要么曾经被清空过,一开始先 \(+v_0\),然后清空,又加了 \(v_1\),再清空,\(+v_2\),清空,……,最后 \(+v_m\),值为 \(v_m\)。不难发现由于我们只关心历史最大值,因此 \(v_1,v_2,\cdots,v_m\) 具体是什么不重要,我们只用关心以下几个值:
- 第一次加的值 \(v_0\),程序中用 \(add\_mx\) 表示。
- 这个值从上一次被标记下推是否被清空,\(clr\)。
- \(\max{v_1,v_2,\cdots,v_m}\),程序中用 \(cov\_mx\) 表示。
- 这个位置当前的值 \(v_m\),程序中用 \(tg\) 表示。
当然除了这四个标记之外,还有每个位置的权值 \(v\) 以及历史最大值 \(hmx\)。
考虑对一个子树清空/整体加值会对标记产生怎样的影响。首先是子树清空,这个比较容易,直接将 \(clr\) 设为 \(1\),\(tg,v\) 设为 \(0\) 即可。其次是整体加值,如果 \(clr\ne 0\) 那就令 \(tg\) 加 \(v\),并将 \(cov\_mx\) 对 \(tg\) 取 \(\max\),否则令 \(add\_mx\) 加 \(v\)。
然后是下推标记的问题,如果 \(clr=0\) 那么直接对左右儿子进行整体 \(+add\_mx\) 操作即可。否则操作等价于先对左右儿子进行 \(+add\_mx\),然后 \(+v_1\),清空,\(+v_2\),清空,……,最后 \(+v_m\),这等价于先对左右儿子进行整体 \(+add\_mx\) 操作,然后令左右儿子的 \(cov\_mx\) 对该节点的 \(cov\_mx\) 取 \(\max\),然后令左右儿子的 \(tg\) 和 \(v\) 都等于 \(tg\)。注意每次操作之后都要实时更新 \(hmx\)。
时间复杂度 \(n\sqrt{m}\)。
const int MAXN=2e5;
const int K=2;
int n,m,res[MAXN+5];pii a[MAXN+5];
struct point{
int x[K+2],id;
point(){memset(x,0,sizeof(x));id=0;}
int& operator [](int id){return x[id];}
} p[MAXN+5];
struct node{int ch[2],v,hmx,add_mx,cov_mx,tg,clr;point val,mn,mx;} s[MAXN+5];
int ncnt=0,rt=0;
void build(int &k,int l,int r){
if(l>r) return;k=++ncnt;
static double avg[K+2],var[K+2];
fill(avg,avg+K,0);fill(var,var+K,0);
for(int i=l;i<=r;i++) for(int j=0;j<K;j++) avg[j]+=p[i][j];
for(int j=0;j<K;j++) avg[j]/=(r-l+1);
for(int i=l;i<=r;i++) for(int j=0;j<K;j++) var[j]+=(p[i][j]-avg[j])*(p[i][j]-avg[j]);
double mx=0;int dim=0;
for(int j=0;j<K;j++) if(mx<var[j]) mx=var[j],dim=j;
int mid=l+r>>1;
nth_element(p+l,p+mid,p+r+1,[&](point x,point y){return x[dim]<y[dim];});
build(s[k].ch[0],l,mid-1);build(s[k].ch[1],mid+1,r);
s[k].val=s[k].mn=s[k].mx=p[mid];
for(int i=0;i<K;i++){
if(s[k].ch[0]) chkmin(s[k].mn[i],s[s[k].ch[0]].mn[i]),chkmax(s[k].mx[i],s[s[k].ch[0]].mx[i]);
if(s[k].ch[1]) chkmin(s[k].mn[i],s[s[k].ch[1]].mn[i]),chkmax(s[k].mx[i],s[s[k].ch[1]].mx[i]);
}
}
void tagclr(int k){s[k].clr=1;s[k].tg=0;s[k].v=0;}
void tagadd(int k,int v){
s[k].v+=v;chkmax(s[k].hmx,s[k].v);s[k].tg+=v;
if(s[k].clr) chkmax(s[k].cov_mx,s[k].tg);
else chkmax(s[k].add_mx,s[k].tg);
}
void pushdown(int k){
if(s[k].add_mx){
if(s[k].ch[0]) tagadd(s[k].ch[0],s[k].add_mx);
if(s[k].ch[1]) tagadd(s[k].ch[1],s[k].add_mx);
s[k].add_mx=0;
} if(s[k].clr){
if(s[k].ch[0]){
s[s[k].ch[0]].clr=1;
chkmax(s[s[k].ch[0]].cov_mx,s[k].cov_mx);
chkmax(s[s[k].ch[0]].hmx,s[k].cov_mx);
s[s[k].ch[0]].tg=s[k].tg;
s[s[k].ch[0]].v=s[k].tg;
} if(s[k].ch[1]){
s[s[k].ch[1]].clr=1;
chkmax(s[s[k].ch[1]].cov_mx,s[k].cov_mx);
chkmax(s[s[k].ch[1]].hmx,s[k].cov_mx);
s[s[k].ch[1]].tg=s[k].tg;
s[s[k].ch[1]].v=s[k].tg;
} s[k].cov_mx=s[k].clr=0;
} s[k].tg=0;
}
void clrpt(int k){pushdown(k);s[k].v=0;}
void addpt(int k,int v){pushdown(k);s[k].v+=v;chkmax(s[k].hmx,s[k].v);}
void modify(int k,int l,int r){
if(!k) return;
if(s[k].mn[0]>r||s[k].mx[1]<l) return tagclr(k),void();
if(l<=s[k].mn[1]&&s[k].mx[0]<=r) return tagadd(k,1),void();
pushdown(k);
if(s[k].val[0]>r||s[k].val[1]<l) clrpt(k);
else addpt(k,1);
modify(s[k].ch[0],l,r);modify(s[k].ch[1],l,r);
}
void dfs(int k){
if(!k) return;res[s[k].val.id]=s[k].hmx;
pushdown(k);dfs(s[k].ch[0]);dfs(s[k].ch[1]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].fi,&a[i].se);
for(int i=1;i<=m;i++) scanf("%d%d",&p[i][0],&p[i][1]),p[i].id=i;
build(rt,1,m);
for(int i=1;i<=n;i++) modify(rt,a[i].fi,a[i].se);
dfs(rt);
for(int i=1;i<=m;i++) printf("%d\n",res[i]);
return 0;
}
/*
8 2
4 5
5 6
2 4
1 3
5 7
6 7
1 6
2 5
4 7
4 5
*/
洛谷 P6349 - [PA2011]Kangaroos(KDT+标记下放)的更多相关文章
- 题解 洛谷 P6349 【[PA2011]Kangaroos】
先考虑对题目进行转化,我们称两个区间有交集为这两个区间能匹配,每个询问就是在序列中最长能连续匹配的长度. 对序列中的一个区间\([l,r]\)和询问的一个区间\([L,R]\),若满足\(L \leq ...
- 洛谷 1083 (NOIp2012) 借教室——标记永久化线段树 / 差分+二分
题目:https://www.luogu.org/problemnew/show/P1083 听说线段树不标记永久化会T一个点. 注意mn记录的是本层以下.带上标记的min! #include< ...
- 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)
点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...
- 洛谷 P6783 - [Ynoi2008] rrusq(KDT+势能均摊+根号平衡)
洛谷题面传送门 首先显然原问题严格强于区间数颜色,因此考虑将询问离线下来然后用某些根号级别复杂度的数据结构.按照数颜色题目的套路,我们肯定要对于每种颜色维护一个前驱 \(pre\),那么答案可写作 \ ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 洛谷 P3391 【模板】文艺平衡树(Splay)
题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...
- 【题解】洛谷P2023 [AHOI2009] 维护序列(线段树)
洛谷P2023:https://www.luogu.org/problemnew/show/P2023 思路 需要2个Lazy-Tag 一个表示加的 一个表示乘的 需要先计算乘法 再计算加法 来自你谷 ...
- [洛谷P2023] [AHOI2009]维护序列
洛谷题目链接:[AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列 ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
随机推荐
- 4.7 80--删除排序数组中的重复项 II
因为python的list可以直接del List[index],因此直接使用了暴力方法,判断是否重复了两次,是的话直接使用del. 在转向使用Java时,因为暴力方法的局限,一直在找怎样对Java的 ...
- airtest keyevent 按键速查表
- 疯狂Java基础Day2
巩固Java流程控制的学习... 一.用户交互Scanner 通过Scanner类获取用户的输入 import java.util.Scanner; public class Demo1 { publ ...
- 结束的NULL
最近同学叫我帮忙看个问题,为啥这个循环没有退出, 代码如下,原本是想拿到最后的NULL指针就可以结束循环 #include <stdio.h> #include <stdlib.h& ...
- WPF进阶技巧和实战03-控件(3-文本控件及列表控件)
系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...
- Kioskcached(1)之 Memcached & Redis & Kioskcached 性能测试对比
前言:本文仅仅是作者自己在学习过程中的一次实验而已,或许因为各种因素会导致实验结果与你之前的认知不太一样,因此请你带着批判的眼光看待本文(本文不具有实际环境的参考性). 一:测试目的 在了解了一些No ...
- SpringCould | Nacos与Feign
服务注册Nacos 介绍 概念 一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. Nacos: Dynamic Naming and Configuration Service Nac ...
- 1. 处理静态资源 2. controller如何接受请求得参数 3. 如何把controller得数据保存到view. 4. 在controller如何完成重定向到指定路径 5. controller返回json数据
1. 1. 处理静态资源2. controller如何接受请求得参数3. 如何把controller得数据保存到view.4. 在controller如何完成重定向到指定路径5. controller ...
- dart系列之:dart语言中的特殊操作符
dart系列之:dart语言中的特殊操作符 目录 简介 普通操作符 类型测试操作符 条件运算符 级联符号 类中的自定义操作符 总结 简介 有运算就有操作符,dart中除了普通的算术运算的操作符之外,还 ...
- Power Platform Center of Excellence (CoE) 部署完成&主要内容说明
随着目前国内使用Power Platform的企业越来越多,而在跟客户交付项目时,客户经常想了解平台的一些基本情况: Power Platform 有多少环境,分别是谁创建和管理? Power Pla ...