http://poj.org/problem?id=2528

题目大意:

贴海报 有先后顺序

会发生覆盖 问你最后漏在外面的有几张海报

思路:

1.所给数据范围比较大,而且是以块为单位 所以首先要离散化排序+把块变成线

2.建树

3.按所给海报顺序进行贴海报 解决覆盖问题

4.搜索一遍 看看有哪些海报是漏在外面的 统计数量

代码及其注释:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
const int N=10005;
struct node1
{
    int l,r;
}mem[N];//所给海报顺序 及其大小
struct node
{
    int k;
    int l,r;
}btree[N*10];//线段树
set<int>str;
bool cansee[N];//是否漏在外面
int a[N*2];
int I;
void build(int x,int i,int j)// 建树
{
    btree[x].k=-1;
    btree[x].l=i;//注意 l 不是直接表示左边界的大小范围 而是范围大小的下表
    btree[x].r=j;
    if(i+1==j)
    return ;
    int mid=(i+j)>>1;
    build(x*2,i,mid);
    build(x*2+1,mid,j);
}
void place(int x,int k,int l,int r)
{
    if(a[btree[x].l]==l&&a[btree[x].r]==r)//如果正好覆盖这一块则不用往下搜了 否则会超时
    {
        btree[x].k=k;
        return ;
    }
    if(btree[x].k>0)
    {
        btree[x*2].k=btree[x].k;//对应上面的 本来是一个整块现在被破坏了 需要把数据向下传
        btree[x*2+1].k=btree[x].k;
        btree[x].k=0;
    }
    int mid=a[(btree[x].l+btree[x].r)>>1];
    if(l>=mid)
    {
        place(x*2+1,k,l,r);
    }else if(r<=mid)
    {
        place(x*2,k,l,r);
    }else
    {
        place(x*2,k,l,mid);
        place(x*2+1,k,mid,r);
    }
}
void find(int x)//最后搜一遍 并记录
{
    cansee[btree[x].k]=true;
    if(btree[x].l+1==btree[x].r||btree[x].k>0)
    return ;
    find(x*2);
    find(x*2+1);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        str.clear();
        for(int i=1;i<=n;++i)
        {
            scanf("%d %d",&mem[i].l,&mem[i].r);
            ++mem[i].r;//块变线
            str.insert(mem[i].l);//用set自动 去重,排序
            str.insert(mem[i].r);
        }
        I=0;
        for(set<int>::iterator t=str.begin();t!=str.end();++t)
        {
            ++I;a[I]=*t;//把set中的数据导入a数组中
        }
        build(1,1,I);//建树
        for(int i=1;i<=n;++i)
        {
            place(1,i,mem[i].l,mem[i].r);//贴海报
        }
        memset(cansee,false,sizeof(cansee));
        find(1);//搜索
        int ans=0;
        for(int i=1;i<=n;++i)
        {
            if(cansee[i])
            ++ans;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted on 2012-06-11 17:20  夜->  阅读(205)  评论(0编辑  收藏  举报