Poj-2528 Mayor's posters

88 篇文章 0 订阅
30 篇文章 0 订阅

题意:
大意就是在一个好长好长(10^7)的墙上贴好多好多(10^4)海报;
海报相互覆盖,求最后能看见多少海报;

题解:
这题给出一个这样的一个墙,显然是要维护一个数据结构嘛;
比如用线段树维护这样子的区间更新(笑);
但是10^7大小我们就这么开一个树必然不行;
所以离散化是必要的;
(我就会这么离散化怎样!)
然后机智的我用了并查集!想看码线段树的失望吧!
把所以区间离线下来,倒序覆盖,这样每个点仅维护一次就可以完成;
f[i]维护这个点后下一个的没有覆盖的点;
用并查集路径压缩f[i];
然后记录海报个数就不是问题了吧;
复杂度大概是O(n)吧。。。总之常数不小但也63ms水过;
//实际上这道题当然也可以线段树做,不过另一道“疯狂的馒头”就不行了,所以我只是想复习一下这样的算法(笑)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 10001
using namespace std;
int f[N<<2],L[N],R[N],dis[N<<4];
bool vis[N];
int cmp(int a,int b)
{
    return a<b;
}
int Find(int x)
{
    return f[x]==x?x:f[x]=Find(f[x]);
}
int main()
{
    int c,T,n,m,i,j,k,l,r,len,ans;
    scanf("%d",&T);
    for(c=1;c<=T;c++)
    {
        if(c!=1)
        {
            memset(f,0,sizeof(f));
            memset(vis,0,sizeof(vis));
            memset(dis,0,sizeof(dis));
        }
        ans=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",L+i,R+i);
            dis[((i-1)<<2)+1]=L[i]-1;
            dis[((i-1)<<2)+2]=L[i];
            dis[((i-1)<<2)+3]=R[i];
            dis[((i-1)<<2)+4]=R[i]+1;
        }
        sort(dis+1,dis+(n<<2)+1,cmp);
        len=unique(dis+1,dis+(n<<2)+1)-dis-1;
        for(i=1;i<=len+1;i++)
        {
            f[i]=i;
        }
        for(i=n;i>0;i--)
        {
            l=lower_bound(dis+1,dis+len+1,L[i])-dis;
            r=lower_bound(dis+1,dis+len+1,R[i])-dis;
            for(j=Find(l);j<=r;j=Find(++j))
            {
                f[j]=Find(j+1);
                if(vis[i]==0)
                {
                    vis[i]++;
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值