线段树练习四

输入输出解释:

第一行两个数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);
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/forget_yu/article/details/77970887
个人分类: 线段树
上一篇2017年8月17日提高组T1 游戏
下一篇2017年9月16日提高组T2 A
想对作者说点什么? 我来说一句

线段树入门

2018年03月29日 1.67MB 下载

没有更多推荐了,返回首页

关闭
关闭