码迷,mamicode.com
首页 > 其他好文 > 详细

【poj2528】Mayor's posters

时间:2018-08-09 23:08:33      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:push   web   数组   lower   shu   webkit   memset   题意   线段树   

题意

给出n个区间,n<=10000, 依次将每个区间涂上不同 的颜色,问最后还能看见多少种颜色

输入 

第一行是一个整数t表示t组数据  对于每组数据:  第1行是n表示有n个区间  接下来n行2个整数L,R表示区间(1<=L<=R<=10000000)

分析

从区间的问题很明显的看出是线段树,做法也很简单,将没有颜色的点标为-1,有多种颜色的区间标为0,有一种颜色的用1~n代表颜色,最后查询出整个区间的颜色数量就行了

但是问题在于区间的范围很大,数组无法承受

所以是一个基础的离散化

离散化的方法简单来说就是通过排序,保持序列l和r的有序性,将排序后的顺序作为新的序号,这样有效地降低了数值大小。

需要注意的是,如果说两端点中间还有其他数,那必须再生成一个节点。

比如 这三对数:1 10  1 3  5 10 答案应该是3,但是离散后答案会变成2,这就是因为中间没生成一个点来代表两数之间的数的原因。

通过unique去重,lower_bound查找要用的节点离散后的位置即可。

#include<bits/stdc++.h>
using namespace std;
#define N 2020000
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (t[p].l+t[p].r>>1)
int T,n,m,tot,ans;
int col[N],num[N],a[N],ls[N],rs[N];
struct email
{
    int l,r,lazy,c;
}t[N*4];

inline void pushnow(int p,int c)
{
    t[p].lazy=c;
    t[p].c=c;
}

inline void pushup(int p)
{
    if(!t[lc].c||!t[rc].c||t[lc].c!=t[rc].c)
        t[p].c=0;
    else
        t[p].c=t[rc].c;
}

inline void pushdown(int p)
{
    if(t[p].lazy!=-1)
    {
        pushnow(lc,t[p].lazy);
        pushnow(rc,t[p].lazy);
        t[p].lazy=-1;
    }
}

void build(int p,int l,int r)
{
    t[p].l=l,t[p].r=r;
    if(l==r)
    {
        t[p].c=-1;
        t[p].lazy=-1;
        return ;
    }
    build(lc,l,mid);build(rc,mid+1,r);
    pushup(p);
}

void update(int p,int ql,int qr,int c)
{
    if(ql<=t[p].l&&t[p].r<=qr)
    {
        pushnow(p,c);
        return;
    }
    pushdown(p);
    if(ql<=mid)update(lc,ql,qr,c);
    if(qr>mid)update(rc,ql,qr,c);
    pushup(p);
}

void query(int p,int ql,int qr)
{
    if(t[p].c==-1)
        return ;
    else
        if(t[p].c>0)
        {
            col[t[p].c]=1;
            return ;
        }
    pushdown(p);
    if(ql<=mid)    query(lc,ql,qr);
    if(qr>mid)     query(rc,ql,qr);
    
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int pl,pr;
            scanf("%d%d",&pl,&pr);
            ls[i]=pl;rs[i]=pr;
            num[i*2-1]=pl;num[i*2]=pr;
        }
        sort(num+1,num+1+2*n);
        m=unique(num+1,num+1+2*n)-(num+1);
        tot=m;
        for(int i=1;i<m;i++)
            if(num[i]+1<num[i+1])
                num[++tot]=num[i]+1;
        sort(num+1,num+1+tot);
        build(1,1,tot);
        memset(col,0,sizeof(col));
        for(int i=1;i<=n;i++)
        {
            int x=lower_bound(num+1,num+1+tot,ls[i])-num;
            int y=lower_bound(num+1,num+1+tot,rs[i])-num;
            update(1,x,y,i);
        }
        query(1,1,tot);
        for(int i=1;i<=n;i++)
            if(col[i])
                ans++;
        printf("%d\n",ans);
    }
    return 0;
}

 

【poj2528】Mayor's posters

标签:push   web   数组   lower   shu   webkit   memset   题意   线段树   

原文地址:https://www.cnblogs.com/NSD-email0820/p/9452069.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!