线段树(build,insert,dfs操作)

模板原型:

解决零散数点在已知线段上的出现次数。思想是将线段用长线覆盖,将长线转化成线段树。用权值记录各个数点出现的次数,最后进行查询。代码解释见注释。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 const int MAXN = 3e4 + 10;
 5 int n,  m,  l,  r;                  //长度n,线段数m
 6
 7
 8 struct line {
 9     int left, right;                //left:左边界 right:右边界
10     int n;                          //该节点的权值
11 } a[MAXN];
12
13 void buildt(int l,  int r,  int step){
14     a[step].left = l;               //建立当前节点的左边界赋值
15     a[step].right = r;              //建立当前节点的右边界赋值
16     a[step].n = 0;                  //初始化当前节点的权值
17     if(l == r)  {return; }          //如果是叶子节点,不进行下面的递归建树操作
18     buildt(l, (l + r) / 2, step * 2); //递归建立左结点
19     buildt((l + r) / 2 + 1, r, step * 2 + 1); //递归建立右结点
20 }
21
22 void dfs(int step){
23     cout << step          << "    "  //当前节点下标
24          << a[step].left  << "    "  //结点左边界
25          << a[step].right << "    "  //结点右边界
26          << a[step].n     << endl;   //结点对应权值
27     if(a[step].left == a[step].right) return;//若为叶子结点,结束当前节点深搜
28     dfs(step * 2);      //递归搜索左结点
29     dfs(step * 2 + 1);  //递归搜索右结点
30     return ;
31 }
32
33 void insert(int s, int t, int step){
34     if(s == a[step].left && t == a[step].right) {
35         ++ a[step].n; //插入的线段匹配则该条线段的记录 +1
36         return ;      //插入操作成功,返回
37     }
38
39     if(a[step].left == a[step].right) //如果当前线段没有子节点,返回
40         return ;
41
42     int mid = (a[step].left + a[step].right) / 2; //二分思想确立中值mid
43
44     if(mid >= t) {              //如果中值在t的右边
45         insert(s, t, step * 2); //则插入到左儿子
46
47     } else if (mid < s) {       //如果中值在s的左边
48         insert(s, t, step * 2 + 1);//则插入到右儿子
49
50     } else {
51         insert(s, mid, step * 2);//否则中点将线段划分,左端到中点部分放入左结点
52         insert(mid + 1, t, step * 2 + 1);//中点到右端部分放入右结点
53     }
54     return ;
55 }
56
57 int main(){
58     cout << MAXN << endl;
59     cin >> n >> m;
60     buildt(0, n, 1);
61     //dfs(1);
62     for(int i = 0; i < m; i ++ ) {
63         cin >> l >> r;
64         insert(l, r, 1);
65     }
66     dfs(1);
67     return 0;
68 }


线段树(build,insert,dfs操作)

时间: 2024-10-30 03:23:50

线段树(build,insert,dfs操作)的相关文章

uva 12299 线段树 点相关的操作模板

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=502&page=show_problem&problem=3720 唯一值得一说的就是shift,变成更新点就行 这道题主要是测试下我做的算法模板 先贴模板 /**************************************************************** 2014.4 By Pilgr

【hdu5306】Gorgeous Sequence 线段树区间最值操作

题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y$ :求 $[x,y]$ 内所有数的和. 多组测试数据,$\sum n,\sum m\le 10^6$ 题解 线段树区间最值操作 对于线段树上的一个节点,维护对应区间的:最大值 $mx$ .最大值个数 $c$ 及严格次大值 $se$ .那么对于一次区间最小值操作: 如果 $t\ge mx$ ,则这个

BZOJ 3779 重组病毒 LCT+线段树(维护DFS序)

原题干(由于是权限题我就直接砸出原题干了,要看题意概述的话在下面): Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒.实验在一个封闭的局域网内进行.局域网内有n台计算机,编号为1~n.一些计算机之间通过网线直接相连,形成树形的结构.局域网中有一台特殊的计算机,称之为核心计算机.根据一些初步的研究,研究员们拟定了一个一共m步的实验.实验开始之前,核

HDU4578 线段树(区间更新 + 多种操作)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578  , 线段树的区间更新 + 多种操作,好题. 虽然是比较裸的线段树,但是比较麻烦,并且有很多细节需要考虑,最后我7.3s很惊险地过了,求大神告知优化方法. 这道题坑在有三种询问:set , add , mul.所以lazy标记要有三个,如果三个标记同时出现的处理方法——当更新set操作时,就把add标记和mul标记全部取消:当更新mul操作时,如果当前节点add标记存在,就把add标记改为:a

线段树一些基本的操作;

更新于2017 4 12 目前学的线段树的操作: 1.某段区间+v: 2.替换某个值(这个代码没涉及0.0) 3.查询区间和,最大值,最小值: 部分代码如下 #include<iostream> #include<cstdio> #include<cstring> #include<cstdio> #inlcude<algorithm> #include<queue> #include<vector> priority_q

hdu1166-敌兵布阵 线段树(对点操作)

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1166 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 86679    Accepted Submission(s): 36535 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子

BZOJ 1798: [Ahoi2009]Seq 维护序列seq (线段树乘法加法的混合操作)

 题目:点击打开链接 大意:一个数组,三个操作,第一种是区间[a,b]每个数乘乘,第二种是区间[a,b]每个数加c,第三种是查询[a,b]区间的和并对p取摸. 两种操作就不能简单的只往下传标记.每次传乘法标记时,要把加法标记同时乘上乘法标记,例如某个区间先进来一个加法标记add,之后又进来一个乘法标记mul. 那么结果为(x + add) * mul = x * mul + add * mul.这样向下传标记的时候就相对独立.递归边界更新加法标记之前先乘上该节点的mul,左右儿子down的时

HDU 5306 Gorgeous Sequence[线段树区间最值操作]

Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2150    Accepted Submission(s): 594 Problem Description There is a sequence a of length n. We use ai to denote the i-th elemen

URAL 1890 . Money out of Thin Air (dfs序hash + 线段树)

题目链接: URAL 1890 . Money out of Thin Air 题目描述: 给出一个公司里面上司和下级的附属关系,还有每一个人的工资,然后有两种询问: 1:employee x y z ,如果编号为x的员工如果工资小于y,就给他加薪z. 2:department x y z ,如果编号为x的员工所管辖的范围内(包括自己),所有员工的工资平均数小于y,给该范围加薪z. 问q次操作后这个公司内每个员工的工资为多少? 解题思路: 根据上司和下级的附属关系,可以先建一个有向图,然后对有向

CCPC河南省赛B-树上逆序对| 离线处理|树状数组 + 线段树维护逆序对 + dfs序 + 离散化

B题地址:树上逆序对 有两个思路 方法一:线段树离线 + 树状数组或者线段树维护区间和 0:离散化,离线存储输入的operation操作序列. ①:先线段树在dfs序上离线处理好整一棵树:在dfs序上先查询"加入当前结点的逆序对权值和"并记录,再加入当前这个节点:dfs完毕后,就已经记录好每个结点的dfs序出入时间戳(转化成区间问题了)和每个 ②:使用树状数组或者新的线段树在dfs序上插入逆序对权值 为什么能这样呢?因为dfs序维护了每个结点遍历的顺序,每个结点的dfs序时间戳肯定比它