二维偏序 tree
tree(二维偏序)
最近接触到一些偏序的东西。
传统线段树非叶子节点的划分点mid=(l+r)/2,但小R线段树mid是自己定的。但满足l<=mid<r,其余条件同原来线段树。那么不难发现如下性质:1.该线段树的节点个数依然为2N-1.2.该线段树深度可能会超过O(logn)。3.该线段树区间定位所包含的线段树节点个数可能超过O(logn)。但区间定位的结果依然是唯一的。小R给你这样一个小R线段树,每次询问给定区间的区间定位个数。
这道题n和询问个数都到了1e5,所以考虑nlogn的做法。
我们发现区间定位个数(答案)和完全被该区间包含的节点个数所相关。具体性质如下:区间定位个数(答案) = 2 * 区间长度 - 完全被该区间包含的节点个数。不难发现完全被该区间包含的节点个可以看作一个森林,而区间定位出的那些线段节点可以看作这些森林当中数的根。由于一个长度为l的根的树的节点个数为 2 ∗ l − 1,那么这个森林当中每有一棵树,就会对“2 * 区间长度”这个总和上减去一,故满足性质。那么我们将问题转化为求完全被该区间包含的节点个数。
那么现在问题就是在所有的区间中,找到[l,r]所完全包含的区间。这是个二维偏序的问题。个人理解所谓二维偏序就是询问许多向量中,比询问的向量小的向量。由于这是偏序关系,所以不是任意两个向量都可以比较大小。这里的定义是如果一个区间l,r,l<=l2,并且r>=r2,那么l,r小于l2,r2。具体做法就是一维排序,然后i从大到小(从小到大也可以,只不过这里dfs出来顺序是从小到大的,那么就从大到小扫一遍),对于左端点在当前询问左端点右侧的区间,把其右侧端点在树状数组里mark一下。然后查询的时候,只查询1到r被mark的值。这样由于只统计了左端点在l右侧的区间,并且区间的右端点被限制在1到r以内,所以所有区间都会被扫到。
感觉这种方法真奇妙。。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=4e5+5;
int n, m, cntseg, cntline, cntq, beg;
int atree[maxn];
struct Node{
int lson, rson, mid;
}node[maxn];
struct Line{
int l, r, id, ans;
void set(const int &x, const int &y){ l=x, r=y; }
}line[maxn], queries[maxn];
bool cmp1(const Line &x, const Line &y){
return x.l==y.l?x.r<y.r:x.l<y.l;
}
bool cmp2(const Line &x, const Line &y){
return x.id<y.id;
}
void build(int &now, int l, int r){
line[cntline++].set(l, r);
if (l==r) return;
if (!now) now=++cntseg;
scanf("%d", &node[now].mid);
build(node[now].lson, l, node[now].mid);
build(node[now].rson, node[now].mid+1, r);
}
inline int lowbit(int x){ return x&(-x); }
void modify(int now){
while (now<=n){
++atree[now];
now+=lowbit(now);
}
}
int query(int now){
int re=0;
while (now){
re+=atree[now];
now-=lowbit(now);
} return re;
}
int main(){
scanf("%d%d", &n, &m);
build(beg, 1, n);
int l, r;
for (int i=0; i<m; ++i){
scanf("%d%d", &l, &r);
queries[cntq].set(l, r);
queries[cntq++].id=i;
}
sort(queries, queries+m, cmp1);
int j=cntline-1;
for (int i=m-1; i>=0; --i){
//如果这个区间,它的左端点在查询的左端点右边
//说明它对查询的左端点是有效果的
while (line[j].l>=queries[i].l){
modify(line[j].r); --j;
}
queries[i].ans=2*(queries[i].r-queries[i].l+1)-query(queries[i].r);
}
sort(queries, queries+m, cmp2);
for (int i=0; i<m; ++i)
printf("%d\n", queries[i].ans);
return 0;
}
二维偏序 tree的更多相关文章
- 洛谷 P1972 [SDOI2009]HH的项链-二维偏序+树状数组+读入挂(离线处理,思维,直接1~n一边插入一边查询),hahahahahahaha~
P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含 ...
- [luogu4479][BJWC2018]第k大斜率【二维偏序+二分+离散化+树状数组】
传送门 https://www.luogu.org/problemnew/show/P4479 题目描述 在平面直角坐标系上,有 n 个不同的点.任意两个不同的点确定了一条直线.请求出所有斜率存在的直 ...
- 【坐标变换】【二维偏序】【线段树】Gym - 100820G - Racing Gems
题意:第一象限有n个点,你从x正半轴任选一个位置出发,vy恒定,vx可以任意变化,不过只能在-vy/r到vy/r之间变化,问你最多能经过多少个点. 暴力dp是n^2,不可取. 注意到,一个点,所能到达 ...
- cdq分治入门学习 cogs 1752 Mokia nwerc 2015-2016 G 二维偏序
/* CDQ分治的对象是时间. 即对于一个时间段[L, R],我们取mid = (L + R) / 2. 分治的每层只考虑mid之前的修改对mid之后的查询的贡献,然后递归到[L,mid],(mid, ...
- 二维偏序+树状数组【P3431】[POI2005]AUT-The Bus
Description Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到 m编号. 每个路口用两个 ...
- 【贪心】【二维偏序】【权值分块】bzoj1691 [Usaco2007 Dec]挑剔的美食家
既然题目中的要求满足二维偏序,那么我们很自然地想到将所有东西(草和牛)都读进来之后,对一维(美味度)排序,然后在另一维(价值)中取当前最小的. 于是,Splay.mutiset.权值分块什么的都支持查 ...
- 【二维偏序】【树状数组】【权值分块】【分块】poj2352 Stars
经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就 ...
- 树状数组 二维偏序【洛谷P3431】 [POI2005]AUT-The Bus
P3431 [POI2005]AUT-The Bus Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 ...
- 【BZOJ1109】[POI2007]堆积木Klo 二维偏序
[BZOJ1109][POI2007]堆积木Klo Description Mary在她的生日礼物中有一些积木.那些积木都是相同大小的立方体.每个积木上面都有一个数.Mary用他的所有积木垒了一个高塔 ...
随机推荐
- DIV CSS 笔记
/*针对谷歌浏览器内核支持的CSS样式*/ <style type="text/css"> @media screen and (-webkit-min-device- ...
- 分享知识-快乐自己:HBase编程
HBase编程: 一):大数据(hadoop)初始化环境搭建 二):大数据(hadoop)环境搭建 三):运行wordcount案例 四):揭秘HDFS 五):揭秘MapReduce 六):揭秘HBa ...
- 将任意一个jQuery对象进行表单序列化,免除了提交请求时大量拼写表单数据的烦恼,支持键值对<name&value>格式和JSON格式。
http://zhengxinlong.iteye.com/blog/848712 将任意一个jQuery对象进行表单序列化,免除了提交请求时大量拼写表单数据的烦恼,支持键值对<name& ...
- hadoop_学习_01_入门准备
一.入门准备 1.零基础学习Hadoop 2.大数据初学者应该知道的知识
- OpenCV——径向模糊
参考来源: 学习OpenCV:滤镜系列(5)--径向模糊:缩放&旋转 // define head function #ifndef PS_ALGORITHM_H_INCLUDED #defi ...
- 基于Ubuntu交叉编译FFmpeg Windows SDK
写在前面 FFmpeg是一个开源且跨平台的音视频解决方案,集采集.转码.流式化为一身,项目的libavcodec编解码模块和libavformat媒体格式模块,支持非常非常丰富的编解码格式和容器封装格 ...
- [转]Google开源Leak Finder—用于检测内存泄漏的JavaScript工具-----可惜,暂时打不开google的网站,下载不了
近日,Google开源了Leak Finder,这款工具可以查看JavaScript应用的堆,进而发现内存泄漏. 作为一门垃圾收集语言,JavaScript并不会出现常见的内存泄露情况,特别是像C++ ...
- 【转】Pro Android学习笔记(三六):Fragment(1):基本概念
目录(?)[-] 为何引入Fragment 大小屏幕的适配 横屏竖屏切换 返回键 什么是Fragment 为何引入Fragment 我们之前的Activity都是都是全屏处理较为简单的单一事务功能,适 ...
- Design:目录
ylbtech-Design:目录 1.返回顶部 1. http://idesign.qq.com/#!index/feed 2. https://www.behance.net/ 3. 2.返回顶部 ...
- 面向对象(Java中普通代码块,构造代码块,静态代码块区别及代码示例)
//执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 //普通代码块:在 ...