poj2528

来源:互联网 发布:阿里云的图标含义 编辑:程序博客网 时间:2024/05/23 02:02
//离散化+线段树+二分#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;#define maxn 10010int n,m,ans;int li[maxn],ri[maxn],hash_color[maxn],a[maxn*2*2*2],color[maxn*16];int Bsearch(int x){    int l=1,r=m,mid;    while(l<=m)    {        mid=(r+l)/2;        if(a[mid]==x) return mid;        else if(a[mid]>x) r=mid-1;        else if(a[mid]<x) l=mid+1;    }    return -1;}void pushdown(int rt){    color[rt*2+1]=color[rt*2]=color[rt];    color[rt]=-1;//down之后把原来的置为不存在}void update(int L,int R,int rt,int c,int l,int r){    if(L<=l && r<=R)    {        color[rt]=c;        return ;    }    if(color[rt]!=-1) pushdown(rt);    int mid=(r+l)/2;    if(L<=mid) update(L,R,rt*2,c,l,mid);    if(mid<R) update(L,R,rt*2+1,c,mid+1,r);}void query(int l,int r,int rt){    if(l==r)    {        if(color[rt]!=-1 &&!hash_color[color[rt]])//这里参考的源程序没有判断color是否为-1,导致c++编译器能ac,g++不能        {            ans++;            hash_color[color[rt]]=true;        }        return ;    }    if(color[rt]!=-1) pushdown(rt);    int mid=(r+l)/2;    query(l,mid,rt*2);    query(mid+1,r,rt*2+1);}int main(){    int t;cin>>t;    while(t--)    {        memset(color,-1,sizeof color);        memset(hash_color,0,sizeof hash_color);        scanf("%d",&n);        m=0;        for(int i=1;i<=n;i++)//在二分函数中li、ri是从1开始,原本这里我写成了i从0开始了        {            scanf("%d%d",&li[i],&ri[i]);            a[++m]=li[i];            a[++m]=ri[i];        }        int tmp=m;        m=1;        sort(a+1,a+tmp+1);        for(int i=2;i<=tmp;i++)//这两个for循环可以实现有序数组的清除重复元素,以及在不连续的两个数间加一个中间数            if(a[i]!=a[i-1]) a[++m]=a[i];        for(int i=m;i>=2;i--)            if(a[i]>a[i-1]+1) a[++m]=a[i]-1;        sort(a+1,a+m+1);        for(int i=1;i<=n;i++)        {            int L=Bsearch(li[i]);            int R=Bsearch(ri[i]);            update(L,R,1,i,1,m);        }        ans=0;        query(1,m,1);        printf("%d\n",ans);    }    return 0;}
原创粉丝点击