POJ-2528-Mayor's posters(线段树)

9 篇文章 0 订阅
6 篇文章 0 订阅

这里写图片描述
Sample Input
1
5
1 4
2 6
8 10
3 4
7 10
Sample Output
4
题意:第一行输入几组样例T,第二行输入n次更新,接下来n行输入每次更新的区间,每次更新在区间上覆盖一种新的颜色,求全部更新完毕之后,最外一层能看到的有几种颜色。
思路:令每种颜色对应一个数字,其中数字0表示未被染色或者被多种颜色染色。
注意:由于l,r过大,需要离散化,但是这里不能直接离散化,直接离散化可能会导致答案错误,比如更新区间是[1,10],[1,3],[7,10]离散l化后变成[1,4],[1,2],[3,4],最后看见的颜色变成2种,但实际上应该是3种。所以这里离散化的时候,先将所有点按从小到大排序,如果是相邻的点可以直接离散化,如果前后两个点相差大于1(比如3、7相差4),则在这两个点之间再添加一个点。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define N  10005
using namespace std;
typedef long long ll;
int vis[10005];
struct node{
    int l,r;
}p[10005];
struct H{
    int val,id,pos;
}h[20010];
struct Tree{
    int l,r;
    int sum,add,num,maxn,col;//num记录最小值
}tree[160000];
bool cmp(struct H x,struct H y)
{
    return x.val<y.val;
}

//col=0表示这个区间内有多个颜色,否则col表示这个区间是哪种颜色 

void pushup(int root){//儿子把信息传递给父亲
    if(tree[root<<1].col!=tree[root<<1|1].col)
    tree[root].col=0;
    else 
    tree[root].col=tree[root<<1].col;
    return ;
}
 void pushdown(int root){//父亲把自己的信息传给儿子
    if(tree[root].l==tree[root].r)return ;
    if(tree[root].add==-1)return ;
    tree[root<<1].add=tree[root<<1|1].add=tree[root].add;
    tree[root<<1].col=tree[root].add;
    tree[root<<1|1].col=tree[root].add;
    tree[root].add=-1;
    return ;
}
//初始化 
void build(int l,int r,int root){
    tree[root].l=l;
    tree[root].r=r;
    tree[root].add=-1;
    if(l==r){//初始状态都为0 
        tree[root].col=0;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,root<<1);//左区间
    build(mid+1,r,root<<1|1); //右区间
    pushup(root);//把儿子的信息更新到父亲
    return;
}
//更新区间 
void update(int l,int r,int z,int root){
    if(l<=tree[root].l&&tree[root].r<=r){
        tree[root].col=z;
        tree[root].add=z;//把要更新的内容保存下来,等到要用儿子时                                    再去更新
        return ;
    }
    pushdown(root);//用父亲的信息更新儿子
    int mid=tree[root].l+tree[root].r>>1;
    if(r<=mid)update(l,r,z,root<<1);
    else if(l>mid)update(l,r,z,root<<1|1);
    else {
        update(l,mid,z,root<<1);
        update(mid+1,r,z,root<<1|1);
    }
    pushup(root);//更新父亲
    return ;
}
//查找区间信息 

int query(int l,int r,int root){
    if(tree[root].col) //如果col≠0,这个区间只有一种颜色这种颜色可能出现过可能没出现过 
    {
        if(!vis[tree[root].col])
        {
            vis[tree[root].col]=1;
            return 1;
        }   
        return 0;       
    }   
    //如果这个点没被染色过 
    if(l==r)return 0;
    //如果这个区间不止一种颜色 
    pushdown(root);
    int mid=tree[root].l+tree[root].r>>1;
    if(r<=mid)return query(l,r,root<<1);
    else if(l>mid)return query(l,r,root<<1|1);
    else return (query(l,mid,root<<1)+query(mid+1,r,root<<1|1));
}

int main(){
    int n,k,t;
    int Case=1;
    char od[50];
    scanf("%d",&t);
    while(t--){
        memset(vis,0,sizeof(vis));
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&p[i].l,&p[i].r);
            h[i*2].val=p[i].l;
            h[i*2].id=i;
            h[i*2].pos=0;
            h[i*2+1].val=p[i].r;
            h[i*2+1].id=i;
            h[i*2+1].pos=1;
        }
        sort(h,h+n*2,cmp);
        int now=0;//当前是第几 
        int last=-1;//前一个数字的大小 
        for(int i=0;i<2*n;i++)
        {
            if(h[i].val!=last)
            {
                if(h[i].val-last==1||now==0) now++;
                else now+=2;
                if(h[i].pos==0)
                p[h[i].id].l=now;
                else p[h[i].id].r=now;
            }
            else
            {
                if(h[i].pos==0)
                p[h[i].id].l=now;
                else p[h[i].id].r=now;
            }
            last=h[i].val;
        }
        build(1,now,1);
        for(int i=0;i<n;i++)
        {
            update(p[i].l,p[i].r,i+1,1);
        }
        printf("%d\n",query(1,now,1)); 

    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值