首页 > 代码库 > 线段树(build,insert,dfs操作)
线段树(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; //插入的线段匹配则该条线段的记录 +136 return ; //插入操作成功,返回37 }38 39 if(a[step].left == a[step].right) //如果当前线段没有子节点,返回40 return ;41 42 int mid = (a[step].left + a[step].right) / 2; //二分思想确立中值mid43 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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。