竞选海报

描述

数码城正在举行市长选举,城中各处贴满了竞选者的海报,这引起了一些市民的不满。因此城市委员会决定建造一座竞选墙,让参加竞选的人把自己的海报统一贴到竞选墙上。张贴海报的规则是:

  • 每一个候选人只能张贴一张海报;
  • 海报的高度和墙的高度一样,而海报的宽度则是任意个 byte 宽(在数码城,byte 是个长度单位);
  • 竞选墙被分成很多段,每段的宽度是一个 byte;
  • 竞选者的海报必须完整地覆盖一串连续的段。

委员会建立的竞选墙长度为 10,000,000 byte。竞选开始后,候选人可以把他们自己的海报张贴出来。然而,一些候选人却把自己的海报贴在了已经张贴了海报的墙面上,从而盖住了别人的海报。数码城的人们都很好奇,最后有几个人的海报是可见(部分或全部)的呢?

你的任务就是在海报宽度、位置和张贴顺序这些数据的基础上,找出最终能有几个竞选者的海报能被人们看到。

输入

输入的第一行是一个整数,它表示数据的组数,之后是各组数据。

每组数据的第一行是一个整数 1 <= n <= 10000。后续的 n 行顺序地记录了 n 张海报张贴的位置,每一行有两个整数 li 和 ri,分别是第 i 张海报所占据的最左和最右段号。已知对于每一个 1 <= i <= n,1 <= li <= ri <= 10,000,000。当第 i 份海报张贴后,它会覆盖从 li, li+1,...ri 的所有段。

输出

针对每一组数据,输出最终可以显示出的海报的份数。

下面的图片展示了输入样例所表示的情形:

 

 测试输入关于“测试输入”的帮助期待的输出关于“期待的输出”的帮助时间限制关于“时间限制”的帮助内存限制关于“内存限制”的帮助额外进程关于“{$a} 个额外进程”的帮助
测试用例 1以文本方式显示
  1. 1↵
  2. 5↵
  3. 1 4↵
  4. 2 6↵
  5. 8 10↵
  6. 3 4↵
  7. 7 10↵
以文本方式显示
  1. 4↵
1秒1024KB0

 

#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#define N 20005  
  
using namespace std;  
  
int tree[N*4], flag[N];  
int a[N],b[N],c[N*2],res;  
  
void update(int p, int s, int e, int l, int r, int v)  
{  
    if(s >= l && e <= r)  
    {  
        tree[p] = v;  
        return;  
    }  
    if(tree[p] != -1)  
    {  
        tree[p<<1] = tree[p<<1|1] = tree[p];  
        tree[p] = -1;  
    }  
    if(l <= ((s+e)>>1)) update(p<<1,s,((s+e)>>1), l, r, v);  
    if(r >((s+e)>>1))   update(p<<1|1,((s+e)>>1)+1,e,l,r,v);  
}  
  
void query(int p, int s, int e)  
{  
    if(tree[p] != -1)  
    {  
        if(!flag[tree[p]]) flag[tree[p]] = 1, ++res;  
        return;  
    }  
    query(p<<1,s,((s+e)>>1));  
    query(p<<1|1,((s+e)>>1)+1,e);  
}  
int compress(int n) //离散压缩   
{  
    int k = 0;  
    for(int i = 0; i < n; ++i)  
    {  
        c[k++] = a[i];  
        c[k++] = b[i];  
        c[k++] = b[i] + 1;  
    }  
    sort(c,c+k);  
    return unique(c, c+k)-c-1;  
}  
  
int main()  
{  
    int t,m,n,l,r;  
    scanf("%d",&t);  
    while(t--)  
    {  
        scanf("%d",&m);  
        for(int i = 0; i < m; ++i) scanf("%d%d", &a[i], &b[i]);  
        n = compress(m);  
        res=0;  
        memset(tree,0,sizeof(tree));  
        memset(flag,0,sizeof(flag));  
        for(int i = 0; i < m; ++i)  
        {  
            l = lower_bound(c, c + n, a[i]) - c + 1;  
            r = lower_bound(c, c + n, b[i]) - c + 1;  
            update(1, 1, n, l, r, i + 1);  
        }  
        flag[0] = 1;  
        query(1, 1, n);  
        printf("%d\n", res);  
    }  
    return 0;  
}  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值