美文网首页
poj2528 线段树+数据离散化

poj2528 线段树+数据离散化

作者: httpsbao | 来源:发表于2019-03-16 20:11 被阅读0次

    题目传送 poj2528

    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1e6+5;//注意数据范围1 <= li <= ri <= 10000000;开大会爆内存
    int a[maxn*3],lazy[maxn*3];
    int al[maxn],ar[maxn];//左右区间数组
    bool book[maxn*3];//标记数组
    void pushdown(int root){ //向下标记
        if(lazy[root]!=-1){
            lazy[root<<1]=lazy[root];
            lazy[root<<1|1]=lazy[root];
            lazy[root]=-1; //记得父节点打回标记
        }
    }
    void updt(int L,int R,int flag,int l,int r,int root){
        if(L<=l&&R>=r){
            lazy[root]=flag;
            return;
        }
        pushdown(root);
        int mid=(l+r)>>1;
        if(L<=mid)updt(L,R,flag,l,mid,root<<1);
        if(R>=mid+1)updt(L,R,flag,mid+1,r,root<<1|1);
    }
    int query(int l,int r,int root){
        if(lazy[root]!=-1){ //如果贴了海报,
            if(book[lazy[root]])return 0; //如果没记录看过这张海报
                book[lazy[root]]=true;//标记已经记录看过这张海报
                return 1;       
        }
        if(l==r)
            return 0;
        int mid=(l+r)>>1;
        int ans=0;
        ans+=query(l,mid,root<<1);
        ans+=query(mid+1,r,root<<1|1);
        return ans;
    }
    int main(){
        int T,N;
        scanf("%d",&T);
        for(int k=1;k<=T;k++){
            scanf("%d",&N);       
            int tag=0;
            for(int i=1;i<=N;i++){
                scanf("%d%d",&al[i],&ar[i]);
                a[++tag]=al[i];//合并
                a[++tag]=ar[i];
            }
            sort(a+1,a+1+tag);//对合并后的数组排序
            tag=unique(a+1,a+1+tag)-(a+1);//去重
            //注意此处错误,if里面语句修改了循环条件tag的值,导致段错误
            /*for(int i=2;i<=tag;i++){
                if(a[i]!=a[i-1]+1){
                    a[++tag]=a[i-1]+1;
                }
            }*/
            for(int i=tag;i>=2;i--){
                if(a[i]!=a[i-1]+1){
                    a[++tag]=a[i-1]+1;
                }
            }
            sort(a+1,a+1+tag);
            memset(lazy,-1,sizeof(lazy));
            memset(book,false,sizeof(book));
            for(int i=1;i<=N;i++){
                int l=lower_bound(a+1,a+tag+1,al[i])-a;
                int r=lower_bound(a+1,a+tag+1,ar[i])-a;
                updt(l,r,i,1,tag,1);//把线段当做点来处理,而不是线段的端点
            }   
            printf("%d\n",query(1,tag,1));
        }
        return 0;
    }
    

    stl函数介绍:
    sort(a+1,a+1+n); 排序,a数组下表从1开始,元素个数为n
    unique(a+1,a+1+n)-(a+1); 去重函数,该函数返回a数组去重之后的元素个数,对于无序数组要先进行排序,因为该函数是对相邻元素去重;执行该函数后a数组变为去重之后的数组,它并不真正把重复的元素删除,是把重复的元素移到后面去了,然后依然保存到了原数组中。
    运行如下:

    unique.png

    lower_bound(a+1,a+n+1,key)-a; 找到有序数组中第一个>=key的数的下标
    upper_bound(a+1,a+n+1,key)-a;用法与lower_bound一样,但是找到的是有序数组中第一个>key的数的下标
    lower_bound函数运行如下:

    lower_bound(1).png
    边界测试:
    lower -bound().png

    相关文章

      网友评论

          本文标题:poj2528 线段树+数据离散化

          本文链接:https://www.haomeiwen.com/subject/wxmopqtx.html