[线段树练习2] 影子的宽度 - 统计标记个数


题目描述

桌子上零散地放着若干个盒子,盒子都平行于墙。桌子的后方是一堵墙。如图所示。现在从桌子的前方射来一束平行光,把盒子的影子投射到了墙上。问影子的总宽度是多少?


输入格式

第1行:3个整数L,R,N。-100000 <=L<=R<= 100000,表示墙所在的区间;1<=N<=100000,表示盒子的个数
接下来N行,每行2个整数BL, BR,-100000 <=BL<=BR<= 100000,表示一个盒子的左、右端点


输出格式

输出仅为一个整数W,表示影子的总宽度。


样例数据

样例输入

1 10 3
3 5
1 4
7 8

样例输出

5


题目分析

统计标记个数(区间修改区间查询)
data直接置1不管懒标记
queryLeft~Right随便乱查
注意要加偏移量
因为C++的负数向0取整,会导致堆式编号出错


源代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline const int Get_Int() {
    int num=0,bj=1;
    char x=getchar();
    while(x<'0'||x>'9') {
        if(x=='-')bj=-1;
        x=getchar();
    }
    while(x>='0'&&x<='9') {
        num=num*10+x-'0';
        x=getchar();
    }
    return num*bj;
}
const int maxn=600000;
struct Tree { //修改区间 查询区间 
    int left,right,data;
};
struct Segment_Tree { //统计标记个数 
    Tree tree[maxn*4];
    int sum;
    void build(int index,int Left,int Right) {
        tree[index].left=Left;
        tree[index].right=Right;
        tree[index].data=0;
        if(Left==Right)return;
        int mid=(Left+Right)/2;
        build(2*index,Left,mid);
        build(2*index+1,mid+1,Right);
    }
    void modify(int index,int Left,int Right) { //增加区间的值
        if(Rightindex].left||Left>tree[index].right)return; //不相交
        if(tree[index].data)return;
        if(Left<=tree[index].left&&Right>=tree[index].right) { //完全包含
            tree[index].data=1;
            return;
        }
        modify(index*2,Left,Right);
        modify(index*2+1,Left,Right);
    }
    void init() { //注意多次询问一定要调用
        sum=0;
    }
    void Query(int index,int Left,int Right) { //查询区间值
        if(Rightindex].left||Left>tree[index].right)return; //不相交
        if(tree[index].data) {
            sum+=tree[index].right-tree[index].left+1;
            return;
        }
        Query(index*2,Left,Right);
        Query(index*2+1,Left,Right);
    }
};
Segment_Tree st;
int Left,Right,n,Delta;
int main() {
    Left=Get_Int();
    Delta=Left-1;
    Left-=Delta;
    Right=Get_Int()-Delta-1;
    st.build(1,Left,Right);
    n=Get_Int();
    for(int i=1; i<=n; i++) {
        int l=Get_Int()-Delta,r=Get_Int()-Delta;
        if(l>r)continue;
        st.modify(1,l,r-1);
    }
    st.init();
    st.Query(1,Left,Right);
    printf("%d\n",st.sum);
    return 0;
}

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