poj2528(线段树+区间离散)

题意:那个城市里要竞选市长,然后在一块墙上可以贴海报为自己拉票,每个人可以贴连续的一块区域,后来帖的可以覆盖前面的,问到最后一共可以看到多少张海报。
思路:一看就知道是线段树,只是说要利用到离散化,也不是那么的难,当然注意,有的离散化错误也ac了......当然,在最后没必要还一个个去询问是否覆盖,直接开个标记数组,询问到一个区间只有一个覆盖值,然后进行标记就可以。

 

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

#define M 100005

struct node

{

    int ll,rr;

    int num;

    int cnt;

}tree[8*M];

int s[4*M][2],t[4*M];

int xx[4*M];

int ans=0,flag=0;

void creat(int i,int l,int r)

{

    tree[i].ll=l;

    tree[i].rr=r;

    tree[i].cnt=0;

    tree[i].num=0;

    int mid=(l+r)/2;

    if(l==r)

    {

        //tree[i].num=0;

        return;

    }

    creat(i*2,l,mid);

    creat(i*2+1,mid+1,r);

}

void updata(int i,int left,int right,int k)

{

    if(tree[i].ll==left&&tree[i].rr==right)

    {

        tree[i].cnt=1;

        tree[i].num=k;

        //if(k==2)

        //printf("%d  %d\n",left,right);

        return;

    }

    if(tree[i].cnt==1)

    {

        tree[i*2].cnt=1;

        tree[i*2+1].cnt=1;

        tree[i*2].num=tree[i].num;

        tree[i*2+1].num=tree[i].num;

        tree[i].cnt=2;

        tree[i].num=0;

    }

    int mid=(tree[i].ll+tree[i].rr)/2;

    if(mid>=right)   updata(i*2,left,right,k);

    else  if(mid<left)   updata(i*2+1,left,right,k);

    else

    {

        updata(i*2,left,mid,k);

        updata(i*2+1,mid+1,right,k);

    }

    if(tree[i*2].cnt==1&&tree[i*2+1].cnt==1&&tree[i*2].num==tree[i*2+1].num)

    {

        tree[i].cnt=1;

        tree[i].num=tree[i*2].num;

    }



    else   tree[i].cnt=2;

    //printf("updata\n");

}

void quest(int i)

{

    //if(k==1)

    //printf("%d  %d  %d  %d  %d\n",tree[i].ll,tree[i].rr,tree[i].cnt,tree[i].num,k);

    if(tree[i].cnt==1)

    {

        xx[tree[i].num]=1;

        return;

    }

    if(tree[i].ll==tree[i].rr)

    return;

    //if(flag==1)

    //return;

    if(tree[i].cnt==0)

    return;

    quest(i*2);

    quest(i*2+1);



   // printf("quest\n");

}

int erfen(int ll,int rr,int num)

{

    while(ll<=rr)

    {

        int mid=(ll+rr)/2;

        if(t[mid]>num)

        rr=mid-1;

        else

        ll=mid+1;

       // printf("erfen\n");

    }

    return rr;

}

int main()

{

    int text;

    scanf("%d",&text);

    while(text--)

    {

        int n;

        scanf("%d",&n);

        //creat(1,1,3*n);

        int cnt=0;

        for(int i=0;i<n;i++)

        {

            scanf("%d%d",&s[i][0],&s[i][1]);

            t[cnt++]=s[i][0];

            t[cnt++]=s[i][1];

        }

        sort(t,t+cnt);

        int cnt1=1;



        for(int i=1;i<cnt;i++)

        if(t[i]!=t[i-1])   t[cnt1++]=t[i];



        for(int i=cnt1-1;i>0;i--)

        if(t[i]!=t[i-1]+1)   t[cnt1++]=t[i-1]+1;

        sort(t,t+cnt1);

        for(int i=cnt1;i>0;i--)

        t[i]=t[i-1];

        creat(1,1,cnt1+5);

        for(int i=1;i<=n;i++)

        {

            int ll=1,rr=cnt1;

            int tmp=erfen(ll,rr,s[i-1][0]);

            int tmp1=erfen(ll,rr,s[i-1][1]);

            //tmp;

            //tmp1;

            //printf("%d %d\n",tmp,tmp1);

            updata(1,tmp,tmp1,i);

        }

        ans=0;

        memset(xx,0,sizeof(xx));

        quest(1);

        for(int i=1;i<=n;i++)

        if(xx[i]==1)

        ans++;

        printf("%d\n",ans);

    }

    return 0;

}

 

 

 

你可能感兴趣的:(poj)