POJ 2528 线段树

坑:
这道题的坐标轴跟普通的坐标轴是不一样的……

此题的坐标轴 标号是在中间的……

线段树建树的时候就不用[l,mid][mid,r]了(这样是错的)
直接[l,mid][mid+1,r]就OK了

Discuss里面的人们很纠结啊…….

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 22222
int cases,n,xx[N],yy[N],q[N],u,ans,vis[N];
struct Tree{int l,r,cover;}tree[N*4];
void build(int l,int r,int pos){
    tree[pos].l=q[l],tree[pos].r=q[r],tree[pos].cover=0;
    if(r==l)return;
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    build(l,mid,lson),build(mid+1,r,rson);
}
void push_down(int pos){
    tree[pos<<1].cover=tree[pos<<1|1].cover=tree[pos].cover;
    tree[pos].cover=0;
}
void insert(int l,int r,int pos,int L,int R,int id){
    if(tree[pos].l>=L&&tree[pos].r<=R){
        tree[pos].cover=id;return;
    }
    if(tree[pos].cover)push_down(pos);
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(tree[lson].r>=R)insert(l,mid,lson,L,R,id);
    else if(tree[rson].l<=L)insert(mid+1,r,rson,L,R,id);
    else insert(l,mid,lson,L,R,id),insert(mid+1,r,rson,L,R,id); 
}
void query(int l,int r,int pos){
    if(tree[pos].cover){if(!vis[tree[pos].cover])vis[tree[pos].cover]=1,ans++;return;}
    if(l==r)return;
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    query(l,mid,lson),query(mid+1,r,rson);
}
int main(){
    scanf("%d",&cases);
    while(cases--){
        memset(vis,0,sizeof(vis)),ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&xx[i],&yy[i]);
            q[i*2-1]=xx[i],q[i*2]=yy[i];
        }
        sort(q+1,q+1+n*2);
        u=unique(q+1,q+1+n*2)-q-1;
        build(1,u,1);
        for(int i=1;i<=n;i++){
            insert(1,u,1,xx[i],yy[i],i);
        }
        query(1,u,1);
        printf("%d
",ans);
    }
}

这里写图片描述

原文地址:https://www.cnblogs.com/SiriusRen/p/6532273.html