[线段树-模板] 线段树+离散化

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第1行为两个整数N和L,分别表示总共贴上的海报数量和宣传栏的宽度。

每组测试数据的第2-N+1行,按照贴上去的先后顺序,每行描述一张海报,其中第i+1行为两个整数a_i, b_i,表示第i张海报所贴的区间为[a_i, b_i]。

对于100%的数据,满足N<=10^5,L<=10^9,0<=a_i&ltb_i<=L。

输出

对于每组测试数据,输出一个整数Ans,表示总共有多少张海报能被看到。

#include <iostream>
#include <cstring>
#include <vector> 
#include <algorithm>
using namespace std; 
struct node{
    int flag; // 海报编号 
    int l,r;  //左端点,右端点 
};
vector<int> v; //用于离散化 
int pt_x[100005],pt_y[100005];  //记录区间端点
node tree[100000*40];  //线段树
bool use[100005*2+10];  //记录能看到的海报
int ans;  //能看到的海报数 

//获得离散值
int getID(int x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}

//建树 
void build(int root,int l,int r){
    tree[root].flag = 0;
    tree[root].l = l;
    tree[root].r = r;
    if(l+1==r)    return;  //到达叶子结点
    int mid = (l+r)/2;
    build(root*2,l,mid);
    build(root*2+1,mid,r); 
    
}
void update(int l,int r,int root,int x){
    if(tree[root].l==l&&tree[root].r==r){
        tree[root].flag = x;
        return;
    }
    if(tree[root].l+1>=tree[root].r) return;  //到达叶子结点
    if(tree[root].flag){  //如果当前区间贴上了海报,其子区间也要更新 
        tree[root*2+1].flag = tree[root*2].flag = tree[root].flag;
        tree[root].flag = 0;
    }
    int mid = (tree[root].l+tree[root].r)/2;
    if(l>mid)  //待更新区间在当前区间的左半边 
        update(l,r,root*2+1,x);
    else if(r<=mid)  //待更新区间在当前区间的右半边 
        update(l,r,root*2,x);
    else{
        //
        update(l,mid,root*2,x);
        update(mid,r,root*2+1,x);
    } 
}

void query(int root){
    if(tree[root].flag&&!use[tree[root].flag]){
        ans++;
        use[tree[root].flag] = 1;
        return;
    }
    if(tree[root].l+1>=tree[root].r) return;  //到达叶子结点
    if(!use[tree[root].flag]){
        query(root*2);
        query(root*2+1);
    }
}

int main(int argc, char** argv) {
    int n,L;
    v.clear();
    memset(tree,0,sizeof(tree)); 
    scanf("%d %d",&n,&L);
    for(int i=0;i<n;i++){
        scanf("%d %d",&pt_x[i],&pt_y[i]);
        v.push_back(pt_x[i]);
        v.push_back(pt_y[i]); 
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int N = v.size();
    build(1,1,N);
    for(int i=0;i<n;i++){
        update(getID(pt_x[i]),getID(pt_y[i]),1,i+1);
    }
    ans = 0;
    memset(use,0,sizeof(use)); 
    query(1);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/jiaqi666/p/9635042.html