POJ2582(Mayor's Posters)

数学模型:给定一个整数序列(最多10000000个数),初始化为0,一共有n(最大10000)个操作,其中第i个操作是将某个指定区间内的数赋值为i,求在经过n次操作后,序列中有多少个不同的非0数

该题可用线段数来做,保存的关键信息为这段的值,最后的查询只有一次。

需要注意的是最多有10000000个数,但n不大,所以可以用离散化处理进行优化。

View Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 10001
#define INF 0x7fffffff
int a[N],b[N],c[2*N],top;
int vis[N];
int id[8*N];
int cmp(const void *a,const void *b)
{
    return (*(int*)a)-(*(int*)b);
}
int Search(int x)
{
    int mid,min=0,max=top;
    while(min+1!=max)
    {
        mid=(min+max)>>1;
        if(c[mid]>x)    max=mid;
        else    min=mid;
    }
    return min;
}
void pushdown(int cur,int x,int y)
{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    if(id[cur])
    {
        id[ls]=id[rs]=id[cur];
        id[cur]=0;
    }
}
void build(int cur,int x,int y)
{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    id[cur]=0;
    if(x==y)    return;
    build(ls,x,mid);
    build(rs,mid+1,y);
}
void change(int cur,int x,int y,int s,int t,int k)
{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    if(x>=s && y<=t)
    {
        id[cur]=k;
        return;
    }
    pushdown(cur,x,y);
    if(mid>=s)  change(ls,x,mid,s,t,k);
    if(mid+1<=t)    change(rs,mid+1,y,s,t,k);
}
int get(int cur,int x,int y)
{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    if(id[cur])
    {
        if(0==vis[id[cur]])
        {
            vis[id[cur]]=1;
            return 1;
        }
        return 0;
    }
    if(x==y)    return 0;
    return get(ls,x,mid)+get(rs,mid+1,y);
}
int main()
{
    int t,n,i;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        top=0;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            c[top++]=a[i];
            c[top++]=b[i];
        }
        qsort(c,top,sizeof(c[0]),cmp);
        top=1;
        for(i=1;c[i];i++)
        {
            if(c[i]!=c[top-1])  c[top++]=c[i];
        }
        c[top]=INF;
        build(1,0,top-1);
        for(i=0;i<n;i++)
        {
            a[i]=Search(a[i]);
            b[i]=Search(b[i]);
            change(1,1,top,a[i]+1,b[i]+1,i+1);
        }
        memset(vis,0,sizeof(vis[0])*(n+1));
        printf("%d\n",get(1,1,top));
    }
    return 0;
}
posted @ 2012-07-12 16:29  BeatLJ  阅读(221)  评论(0编辑  收藏  举报