线段树

主要运算:

离散化(可选,当输入数据很大时有用)

建树

插入线段

统计

 

入门:

http://hi.baidu.com/alpc62/blog/item/469edeca0043e382c8176875.html

题目1: 所有的数不大于30000的范围内讨论一个问题:现在已知n条线段,把端点依次输入告诉你,然后有m个询问,每个询问输入一个点,要求这个点在多少条线段上出现过;

 

代码

 1 线段树 #include  < stdio.h >
 2 线段树#include  < assert.h >
 3 线段树
 4 线段树 // 在自然数,且所有的数不大于30000的范围内讨论一个问题:现在已知n条线段,把端点依次输入告诉你,
 5 线段树 // 然后有m个询问,每个询问输入一个点,要求这个点在多少条线段上出现过;
 6 线段树
 7 线段树 #define  MAX_NUM_PT 1000
 8 线段树 #define  MAX_TREE_SIZE (MAX_NUM_PT*(MAX_NUM_PT+1)/2)
 9 线段树
10 线段树 struct  line
11 线段树 {
12线段树      int left,right;//左端点、右端点
13线段树      int n;//记录这条线段出现了多少次,默认为0, 每个结点的左右儿子位置为2n,2n+1
14线段树}
a[MAX_TREE_SIZE];
15 线段树
16 线段树
17 线段树 void  buildTree( int  s, int  t,  int  k)     // 要插入的线段的左端点和右端点,插入位置
18 线段树 {
19线段树    a[k].left = s;
20线段树    a[k].right = t;
21线段树    a[k].n = 0;
22线段树    
23线段树    assert(k<=MAX_TREE_SIZE);
24线段树
25线段树    if(t>s)
26线段树    {
27线段树        int mid = (s+t)/2;
28线段树        
29线段树        buildTree(s, mid, 2*k+1);
30线段树        buildTree(mid+1, t, 2*k+2);
31线段树    }

32线段树}

33 线段树
34 线段树 void  insert( int  s, int  t, int  step) // 要插入的线段的左端点和右端点、插入位置
35 线段树 {
36线段树      if (s==a[step].left && t==a[step].right)
37线段树      {
38线段树            a[step].n++;//插入的线段匹配则此条线段的记录+1
39线段树            return;//插入结束返回
40线段树      }

41线段树      if (a[step].left==a[step].right)   return;//当前线段树的线段没有儿子,插入结束返回
42线段树      int mid=(a[step].left+a[step].right)/2;
43线段树      if (mid>=t)    insert(s,t,step*2+1);//如果中点在t的右边,则应该插入到左儿子
44线段树      else if (mid<s)    insert(s,t,step*2+2);//如果中点在s的左边,则应该插入到右儿子
45线段树      else//否则,中点一定在s和t之间,把待插线段分成两半分别插到左右儿子里面
46线段树      {
47线段树            insert(s,mid,step*2+1);
48线段树            insert(mid+1,t,step*2+2);
49线段树      }

50线段树}

51 线段树
52 线段树 int  FindN( int  pt,  int  k)     // 查询数据pt, 位置k
53 线段树 {
54线段树    int num = a[k].n;
55线段树
56线段树    assert (pt>=a[k].left && pt<=a[k].right);
57线段树
58线段树    if (a[k].left<a[k].right)
59线段树    {
60线段树        assert(a[k*2+1].right<a[k*2+2].left);
61线段树
62线段树        if(pt<=a[k*2+1].right)
63线段树            num += FindN(pt, k*2+1);
64线段树
65线段树        else if(pt>=a[k*2+1].left)
66线段树            num += FindN(pt, k*2+2);
67线段树    }

68线段树
69线段树    return num;
70线段树}

71 线段树 void  main()
72 线段树 {
73线段树    buildTree(0,4,0);    //根节点区间为[0,4]
74线段树    insert(1,3,0);        //插入线段[1,3]
75线段树    insert(2,3,0);    
76线段树    insert(2,4,0);
77线段树
78线段树    //统计每个节点的线段覆盖数目
79线段树    for (int n=0; n<=4;n++)
80线段树    {
81线段树        printf("Point %d, num %d\n",n,FindN(n,0));
82线段树    }

83线段树}

 

你可能感兴趣的:(线段树)