关闭

线段树练习四

44人阅读 评论(0) 收藏 举报
分类:

输入输出解释:

第一行两个数n,m
表示长度为n的线段
接下来的m行读入x,y
表示在[x,y]的区间中加入一条线段
最后一行两个数x,y
输出x到y这一个区间中的线段数
保证x+1=y
样例输入 :
7 5
2 3
2 5
2 4
4 5
2 4
2 4
样例输出:
3
做法:
当某线段能够完整覆盖某个结点所对应的区间时,则不再二分。因此要统计某个单位区间上重叠的线段总数,必须把从叶结点到根结点路径上所有结点的count域累加
代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int c[500000],n,m,e=0;

void insert(int t,int l,int r,int a,int b)
{
    int m=(l+r) / 2;
    if (l==a && r==b)
    {
        c[t]++;
    }
    else
    {
        if (b<=m)   insert(t*2,l,m,a,b);
        else if (a>=m)  insert(t*2+1,m,r,a,b);
        else
        {
            insert(t*2,l,m,a,m);
            insert(t*2+1,m,r,m,b);
        }
    }
}

void find(int t,int l,int r,int a,int b)
{
    int m=(l+r) / 2;
    if (l==a && r==b)
    {
        e=t;
        return;
    }
    else
    {
        if (b<=m)   find(t*2,l,m,a,b);
        else if (a>=m)  find(t*2+1,m,r,a,b);
        else
        {
            find(t*2,l,m,a,m);
            find(t*2+1,m,r,m,b);
        }
    }
}

int count(int t)
{
    int sum=0;
    while (t>0)
    {
        sum+=c[t];
        t/=2;
    }
    return sum;
}

int main()
{
    scanf("%d%d",&n,&m);
    int x,y;
    for (int p=1;p<=m;p++)
    {       
        scanf("%d%d",&x,&y);
        insert(1,1,n,x,y);
    }
    scanf("%d%d",&x,&y);
    find(1,1,n,x,y);    
    int ans=count(e);
    printf("%d",ans);
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:12269次
    • 积分:1638
    • 等级:
    • 排名:千里之外
    • 原创:135篇
    • 转载:0篇
    • 译文:0篇
    • 评论:200条
    最新评论