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的更多相关文章

  1. 洛谷 P1972 [SDOI2009]HH的项链-二维偏序+树状数组+读入挂(离线处理,思维,直接1~n一边插入一边查询),hahahahahahaha~

    P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含 ...

  2. [luogu4479][BJWC2018]第k大斜率【二维偏序+二分+离散化+树状数组】

    传送门 https://www.luogu.org/problemnew/show/P4479 题目描述 在平面直角坐标系上,有 n 个不同的点.任意两个不同的点确定了一条直线.请求出所有斜率存在的直 ...

  3. 【坐标变换】【二维偏序】【线段树】Gym - 100820G - Racing Gems

    题意:第一象限有n个点,你从x正半轴任选一个位置出发,vy恒定,vx可以任意变化,不过只能在-vy/r到vy/r之间变化,问你最多能经过多少个点. 暴力dp是n^2,不可取. 注意到,一个点,所能到达 ...

  4. cdq分治入门学习 cogs 1752 Mokia nwerc 2015-2016 G 二维偏序

    /* CDQ分治的对象是时间. 即对于一个时间段[L, R],我们取mid = (L + R) / 2. 分治的每层只考虑mid之前的修改对mid之后的查询的贡献,然后递归到[L,mid],(mid, ...

  5. 二维偏序+树状数组【P3431】[POI2005]AUT-The Bus

    Description Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到 m编号. 每个路口用两个 ...

  6. 【贪心】【二维偏序】【权值分块】bzoj1691 [Usaco2007 Dec]挑剔的美食家

    既然题目中的要求满足二维偏序,那么我们很自然地想到将所有东西(草和牛)都读进来之后,对一维(美味度)排序,然后在另一维(价值)中取当前最小的. 于是,Splay.mutiset.权值分块什么的都支持查 ...

  7. 【二维偏序】【树状数组】【权值分块】【分块】poj2352 Stars

    经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就 ...

  8. 树状数组 二维偏序【洛谷P3431】 [POI2005]AUT-The Bus

    P3431 [POI2005]AUT-The Bus Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 ...

  9. 【BZOJ1109】[POI2007]堆积木Klo 二维偏序

    [BZOJ1109][POI2007]堆积木Klo Description Mary在她的生日礼物中有一些积木.那些积木都是相同大小的立方体.每个积木上面都有一个数.Mary用他的所有积木垒了一个高塔 ...

随机推荐

  1. php 简单笔记

    1.时间 $date1 = "2014-11-11"; echo date('Y-m-d',strtotime("$date1 +5 day")); //输出结 ...

  2. Python—numpy.bincount()

    1.它大致说bin的数量比x中的最大值大1,每个bin给出了它的索引值在x中出现的次数.下面,我举个例子让大家更好的理解一下: # 我们可以看到x中最大的数为7,因此bin的数量为8,那么它的索引值为 ...

  3. Selenium-键盘操作

    在webdriver的Keys类中提供了键盘所有的按键操作,当然也包括一些常见的组合操作如Ctrl+A全选),Ctrl+C(复制),Ctrl+V(粘贴).更多参考官方文档对应的编码http://sel ...

  4. Java 使用itext生成pdf以及下载

    使用方法: 1.需要两个jar包: iText-5.0.6.jar    //必须使用该版本,否则缺少相关的方法 TextAsian.jar //是为了文档中正常显示中文所必须引用的包 TextAsi ...

  5. Linux Shell 判断块设备节点是否存在

    /************************************************************************* * Linux Shell 判断块设备节点是否存在 ...

  6. bzoj 3171: [Tjoi2013]循环格 最小费用最大流

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3171 题解: 首先我们很容易发现一个结论: 出现完美循环当且仅当所有点的出入度均为1 所 ...

  7. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  8. 删除文件时提示 你需要来自system的权限才能对此文件夹进行更改

    问题描述: 我的计算机是Win7 x64操作系统,在我的计算机的F盘中,不知道什么时候多了个“12e4k69m762nzcgt8zx”这样一个文件夹,应该是某个软件自己创建并留下的文件夹,想删除掉则提 ...

  9. XML的二十个热点问题

    这些日子,几乎每个人都在谈论XML (Extensible Markup Language),但是很少有人真正理解其含义.XML的推崇者认为它能够解决所有HTML不能解决的问题,让数据在不同的操作系统 ...

  10. 找工作--volatile

    在Java编写的程序中,有时为了提高程序的运行效率,编译器会自动对其进行优化,把经常访问的变量缓存起来,程序在读取这个变量时有可能会直接从缓存(例如寄存器)中来读取这个值,而不会从内存中读取.这样做的 ...