poj 2528 (线段树+离散化)

 
 

    大致题意:     
          有一面墙,被等分为1QW份,一份的宽度为一个单位宽度。现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW。后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报。现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报        
       线段树就不说了》》主要是离散化怎么处理。。。
    
    转:        离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9对其升序排序,得2 3 4 6 8 9 10然后建立映射2     3     4     6     8     9   10↓     ↓      ↓     ↓     ↓     ↓     ↓1     2     3     4     5     6     7那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。 离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。
     
    
    
    User: 1013101127
    Memory: 2180K Time: 610MS
    Language: G++ Result: Accepted
    Source Code
    #include <iostream>
    #include <string>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int cas;
    int n;
    
    
    int logo[100008][3];
    struct poit
    {
        int pp;
        int num;
    }mem[100400*3];
    
    
    int f[100008];
    int ans=0;
    
    
    bool cmp(poit a,poit b)
    {
        return a.num<b.num;
    }
    
    
    struct node
    {
        int color;
        int l;
        int r;
    }p[100009];
    
    
    void built(int t,int lc,int rc)//建树
    {
        p[t].l=lc;
        p[t].r=rc;
        p[t].color=0;
        if(lc==rc)return ;
        built(2*t,lc,(lc+rc)/2);
        built(2*t+1,(lc+rc)/2+1,rc);
    }
    
    
    void change(int t,int lc,int rc,int col)//更新各点
    {
        if(p[t].l==lc&&p[t].r==rc)
        {
            p[t].color=col;
            return ;
        }
        if(p[t].color>0&&p[t].color!=col)
        {
            p[2*t].color=p[2*t+1].color=p[t].color;
            p[t].color=0;
        }
        int mid=(p[t].l+p[t].r)/2;
        if(rc<=mid)
        change(2*t,lc,rc,col);
        else if(lc>mid)
        change(2*t+1,lc,rc,col);
        else
        {
            change(2*t,lc,mid,col);
            change(2*t+1,mid+1,rc,col);
        }
    }
    
    
    void query(int t)//查找
    {
        if(p[t].color!=0)
        {
            if(!f[p[t].color])
            {
                f[p[t].color]=1;
                ans++;
            }
            return ;
        }
        query(2*t);
        query(2*t+1);
    }
    
    
    
    
    int main()
    {
        cin>>cas;
        while(cas--)
        {
            cin>>n;
            for(int i=0;i<n;i++)
            {
                cin>>logo[i][0]>>logo[i][1];
                mem[i*2].pp=-(i+1);
                mem[i*2].num=logo[i][0];
                mem[i*2+1].pp=(i+1);
                mem[i*2+1].num=logo[i][1];
            }
    
    
            sort(mem,mem+2*n,cmp);
    
    
            int tmp=mem[0].num;
            int sum=1;
            for(int i=0;i<2*n;i++)
            {
                if(mem[i].num!=tmp)
                {
                    sum++;
                    tmp=mem[i].num;
                }
                if(mem[i].pp<0)
                {
                    logo[-mem[i].pp-1][0]=sum;
                }
                else
                {
                    logo[mem[i].pp-1][1]=sum;
                }
            }
            built(1,1,sum);
            for(int i=0;i<n;i++)
            {
               change(1,logo[i][0],logo[i][1],i+1);
            }
            memset(f,0,sizeof(f));
            ans=0;
            query(1);
            cout<<ans<<endl;
        }
        return 0;
    }



你可能感兴趣的:(struct,user,query,ini)