poj 2528 Mayor's posters(线段树,离散化)

第一次写这么长的代码...

题意:

有一长为107的区间,给n个区间染色,问最后可以看到几种颜色。(1≤n≤104

思路:

区间问题比较适合用线段树处理,因为区间较大,需要将端点离散化集中起来减小内存开支。

Tips:

cstdio是79MS,iostream是625MS。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int M=22000;

int tree[M<<4];//完全二叉树存储线段树
int lf[M],rt[M];//存储输入区间左右端点
int ls[3*M],ans;//存储离散化后的新端点
bool vis[3*M];//该颜色是否已计入ans

void pushdown(int p)
{
    tree[p<<1]=tree[(p<<1)|1]=tree[p];
    tree[p]=-1;
}

void update(int p,int l,int r,int x,int y,int v)//给p点l~r区间内的x~y区间染上v色
{
    if(x<=l&&y>=r)//如果该区间被x~y完全覆盖,染上v色
    {
        tree[p]=v;
        return;
    }
    
    if(tree[p]!=-1) pushdown(p);//若原区间不能被x~y完全覆盖且已染色,将原区间颜色推至子区间,原区间颜色置空
    
    int mid=(l+r)>>1;
    if(y<=mid) update(p<<1,l,mid,x,y,v);//两区间关系分情况讨论,继续为子区间染色
    else if(x>mid) update((p<<1)|1,mid+1,r,x,y,v);
    else update(p<<1,l,mid,x,mid,v),update((p<<1)|1,mid+1,r,mid+1,y,v);
}

void query(int p,int l,int r)//从p点开始下查l~r区间有多少种颜色
{
    if(tree[p]!=-1)//如果该区间已被染色
    {
        if(!vis[tree[p]])//如果该颜色没有计入答案
        {
            ++ans;
            vis[tree[p]]=true;
        }
        return;
    }
    if(l==r) return;//如果已访问到底部端点
    
    int mid=(l+r)>>1;
    query(p<<1,l,mid);//如果该区间染色状况不明,继续向下访问子区间
    query((p<<1)|1,mid+1,r);
}

int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        int n;scanf("%d",&n);
        memset(tree,-1,sizeof(tree));//标记为未染色
        memset(vis,false,sizeof(vis));

        int len=0;
        for(int i=0;i<n;i++)//存储输入区间左右端点
        {
            scanf("%d%d",&lf[i],&rt[i]);
            ls[len++]=lf[i];
            ls[len++]=rt[i];
        }

        sort(ls,ls+len);
        int len2=unique(ls,ls+len)-ls;//离散化,排序
        int t=len2;
        for(int i=1;i<t;i++)
        {
            if(ls[i]-ls[i-1]>1)//如果有区间长度大于2,插入一个端点,防止类似于(1,10)(1,4)(4,6)的情况
                ls[len2++]=ls[i-1]+1;
        }
        sort(ls,ls+len2);

        for(int i=0;i<n;i++)//x,y为离散化后原端点的映射端点
        {
            int x=lower_bound(ls,ls+len2,lf[i])-ls+1;
            int y=lower_bound(ls,ls+len2,rt[i])-ls+1;
            update(1,1,len2,x,y,i);
        }
        ans=0;
        query(1,1,len2);
        printf("%d\n",ans);
    }

    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Kanoon/p/12600827.html