//线段树模板一 链表版
//功能:在自然数,且所有的数不大于30000的范围内讨论一个问题:现在已知n条线段,把端点
//依次输入告诉你,然后有m个询问,每个询问输入一个点,要求这个点在多少条线段上出现
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct treel{
int left,right; //左端点 右端点
int num; //记录这条线段出现过多少次
struct treel *lc,*rc;
};
struct treel *build(int l,int r)
{
treel *root= new treel;
root->left=l;root->right=r;
root->num=0;
int mid=(root->left+root->right)>>1;
if(l!=r) //成立表示此端点不是叶子节点
{
root->lc=build(l,mid);
root->rc=build(mid+1,r);
}
return root;
}
void Insert(int c,int d,treel *root)
{
if(c==root->left&&d==root->right) //结果匹配
{
root->num++;
return ;
}
if(c==d) return ; //到达最低段
int mid = (root->left+root->right)>>1;
if(c>mid) Insert(c,d,root->rc); //如果左端点比中点还大,则要插到右子树中去
else if(d<=mid) Insert(c,d,root->lc);
else { Insert(c,mid,root->lc); Insert(mid+1,d,root->rc); }
}
int sum=0; //标记要查询的线段出现过多少次
//查询过程和插入过程相似
void Find(int c,int d,treel *root)
{
if(c==root->left&&d==root->right)
{
sum+=root->num;
return ;
}
if(root->left==root->right) return ;
int mid = (root->left+root->right)>>1;
if(c>mid) Find(c,d,root->rc);
else if(d<=mid) Find(c,d,root->lc);
else { Find(c,mid,root->lc); Find(mid+1,d,root->rc); }
sum+=root->num;
}
//层序遍历输出
void levalorder(struct treel *root)
{
struct treel *queue[100];
int rear=0,front=-1;
if(!root)
return ;
queue[rear]=root;
while(front!=rear)
{
front++;
printf("%d ",queue[front]->num);
//将左孩子结点入队
if(queue[front]->lc)
{
rear++;
queue[rear]=queue[front]->lc;
}
//将右孩子节点入队
if(queue[front]->rc)
{
rear++;
queue[rear]=queue[front]->rc;
}
}
}
int main()
{
struct treel *root=build(0,7);
Insert(2,5,root);
Insert(4,6,root);
Insert(0,7,root);
sum=0; Find(2,3,root); cout<<sum<<endl;
//levalorder(root);
return 0;
}
线段树模板一
最新推荐文章于 2017-07-11 01:28:50 发布