海报详解

来源:互联网 发布:centos 6.8 安装pptp 编辑:程序博客网 时间:2024/06/11 04:40
#include<stdio.h>#include<stdlib.h>#include<string.h>#define N 10010struct node{    int x1,x2;}s[N];int vis[N],st[2*N],str[4*N],ys,count;struct node1{    int l,r;    int cp;//标记该节点是否被某张海报完全覆盖}tree[16*N];//在添加顶点之后,最坏情况下,顶点数会达到4*Nint cmp(const void *a,const void *b){    return *(int *)a - *(int *)b;}int find(int x){    //必须找得到    int mid,l,r;    l=1;    r=ys;    while(r>=l)//向中间逼近     {        mid=(l+r)/2;        if(str[mid]>x) r=mid-1;        else if(str[mid]<x) l=mid+1;        else return mid;    }}void bulid(int l,int r,int t)//普通建树 {    int mid;    tree[t].l=l;    tree[t].r=r;    tree[t].cp=0;    if(l==r) return;    mid=(l+r)/2;    bulid(l,mid,2*t);    bulid(mid+1,r,2*t+1);}void updata(int l,int r,int t,int num){    if(tree[t].l==l && tree[t].r==r)    {        tree[t].cp=num;//颜色覆盖         return;    }        if(tree[t].cp!=0)//已覆盖     {        tree[2*t].cp=tree[2*t+1].cp=tree[t].cp;//颜色向下传 ,不过这一步又是为什么         tree[t].cp=0;    }            if(r<=tree[2*t].r) updata(l,r,2*t,num);        else if(l>=tree[2*t+1].l) updata(l,r,2*t+1,num);        else    {        updata(l,tree[2*t].r,2*t,num);        updata(tree[2*t+1].l,r,2*t+1,num);    }    }void query(int t){    if(tree[t].cp!=0) //已覆盖,未访问     {        if(vis[tree[t].cp]==0)        {            count++;//计算几种颜色             vis[tree[t].cp]=1;//这种颜色已经算过了         }        return;    }    if(tree[t].l==tree[t].r) return;//不断查询     query(2*t);    query(2*t+1);}int main(){    int i,n,ncase,k,ans1,ans2;    scanf("%d",&ncase);    while(ncase--)    {        scanf("%d",&n);        k=0;        for(i=1;i<=n;i++)        {            scanf("%d%d",&s[i].x1,&s[i].x2);            k++;            st[k]=s[i].x1;            k++;            st[k]=s[i].x2;        }        qsort(st+1,k,sizeof(st[1]),cmp);//比较k次,k为点数 ,把所有的点排序         ys=1;//1 待排序数组首地址2 数组中待排序元素数量3 各元素的占用空间大小4 指向函数的指针,用于确定排序的顺序        str[1]=st[1];        for(i=2;i<=k;i++)//n条边,k个点         {            if(st[i]!=st[i-1])//点不相重             {                if(st[i]!=st[i-1]+1) //如果不是我要改一下                 {                    ys++;                    str[ys]=st[i-1]+1;                 }                ys++;                str[ys]=st[i];//如果是的话就直接等下去好了 ,str存离散化后的点             }        }//增加顶点,并除去相等的顶点。      printf("%d\n",ys);        bulid(1,ys,1);//对这些点建树,ys为1-ys建树,即点数                         for(i=1;i<=n;i++)//其实这算是初始化 ,回去找点         {            ans1=find(s[i].x1);            ans2=find(s[i].x2);//二分找到边界            printf("%d %d\n",ans1,ans2);            updata(ans1,ans2,1,i);        }        memset(vis,0,sizeof(vis));//初始化         count=0;        query(1);//遍历一次,查询        printf("%d\n",count);//输出     }    return 0;}

0 0