标签:void 多少 属性 margin 线段树 name struct color 时间复杂度
惊了,从别人那里偷了一个dfs序。世界真神奇
dfs序什么意思呢,就是对dfs走过的地方进行标序,每个节点建立一个
struct node{
int in,out;
.........
};
这个in就是你什么时候进入这个节点,out就是什么时候从这个节点出来,程序也很好实现,加个计数cnt就行了,遍历一遍,
{ in = ++cnt;
dfs(。。。。);
out = cnt; }
大致就是这个样子
那么dfs序有什么用呢,脑补一下,每个节点我都做成了一个区间,并包括他所有的子区间(子节点)
一般用线段树管理,时间复杂度就下来了
再说一下为什么时间复杂度会下来,因为用到 dfs序+线段树 这种题一般都是多个修改,多个查询,点还特别多,
问题一般还是问你某个节点后面有多少个含有某种属性的节点(比如说每个节点都有一种颜色,他问你后面的节点中红色有多少个)
不用这个的话每次查询就是遍历后面的所有点,基本一次查询就是n(一共n个节点)的复杂度,m次查询就是O(m*n),基本都是超时
线段树查询 logn,一下子时间就降下来了
1
2 3
4 5 6
用dfs排完序那么就是 1是(1,6) 2是(2,3) 3是(4,6) 4是(3,3) 5是(5,5) 6是(6,6)
现在用线段树构造
(1,6) (1,6)
(2,3) (4,6) (1,3) (4,6)
(3,3) (5,5) (6,6) (1,2) (3,3) (4,5) (6,6)
(1,1) (2,2) (4,4) (5,5)
左边的(1,6)是第一个点 它的值等于右边的(1,1)
代码:
#include <iostream>
#include <vector>
using namespace std;
const int N = 1e5 + 5;
int cnt = 0,in[N],out[N],pre[N],arr[N];
vector<int> pp[N];
//pp[i]装的是i后面紧连着的字节点
void dfs(int n)
{
for(int i = 0;i < pp[n].size(); ++i)
{
int d = pp[n][i];
in[d] = ++cnt;
pre[cnt] = d;//pre存储的是in值对应的点
dfs(d);
out[d] = cnt;
}
}
int main()
{
in[1] = 1;
out[1] = n;
}
标签:void 多少 属性 margin 线段树 name struct color 时间复杂度
原文地址:http://www.cnblogs.com/mltang/p/7775070.html