poj 2528 Mayor's posters

Mayor’s posters
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 59553 Accepted: 17255
Description

The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for placing the posters and introduce the following rules:
Every candidate can place exactly one poster on the wall.
All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown).
The wall is divided into segments and the width of each segment is one byte.
Each poster must completely cover a contiguous number of wall segments.

They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections.
Your task is to find the number of visible posters when all the posters are placed given the information about posters’ size, their place and order of placement on the electoral wall.
Input

The first line of input contains a number c giving the number of cases that follow. The first line of data for a single case contains number 1 <= n <= 10000. The subsequent n lines describe the posters in the order in which they were placed. The i-th line among the n lines contains two integer numbers li and ri which are the number of the wall segment occupied by the left end and the right end of the i-th poster, respectively. We know that for each 1 <= i <= n, 1 <= li <= ri <= 10000000. After the i-th poster is placed, it entirely covers all wall segments numbered li, li+1 ,… , ri.
Output

For each input data set print the number of visible posters after all the posters are placed.

The picture below illustrates the case of the sample input.

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10
Sample Output

4
Source

Alberta Collegiate Programming Contest 2003.10.18
这题大致来说就是线段树+区间离散化。
但是离散化的时候有许多细节需要注意。
下面说一说Discuss里面一个大神关于离散化需要注意的一些事情:
1.我建的是段树,也就是:
|_|_|__|
1 2 3
这样子的。
2,3,4那组数据中比较有争议的一组是:
3
5 6
4 5
6 8
如果不离散化直接算覆盖的话,是这样的:(暂且忽略前面的1-4..)
… |_|_|__|
6 7 8
|_|_|
4 5
|_|_|
5 6
显然答案为2啦。(从顶往底看,注意输入顺序)
然后离散化之后,
如果不注意数值相同,就会变成这样:
3 4
1 2
5 6
数值相同后离散就是这样:
2 3
1 2
3 4
|_|_|
3 4
|_|_|
1 2
|_|_|
2 3
这就对了。

但是,离散化得再注意到下面这个问题:
1 10
1 3
6 10
这组数据,不离散化是这样的:
|_|_|_|_|__|
6 7 8 9 10
|_|_|__|
1 2 3
|_|_|_|_|_|_|_|_|_|_|
1 2 3 4 5 6 7 8 9 10
显然答案为3.
如果我们使用上面的“注意到数值相同的离散化”,结果是这样的:
1 4
1 2
3 4
画出来是这样的:
|_|_|
3 4
|_|_|
1 2
|_|_|_|_|
1 2 3 4
然后坑就出现了..
我的解决方案是,

|_|_|
↓ 3 4
|_|_|
1 2
|_|_|_|_|
1 2 3 4

在离散化时出现了海报右端序号在前,左端序号在后,且序号不等(也就是离散后会相邻的情况):

|_|_|
↓ 3 4
|_|_|
1 2
这两个就属于离散化后相邻的情况
我加上1:
变成这样:
1 5
1 2
4 5
|_|_|
4 5
|_|_|
1 2
|_|_|_|_|__|
1 2 3 4 5
可能会有人问,要是是这样的呢?
3
1 4
1 2
3 4
本来就相邻的情况呢?
这样的话,提取原来的序号,比较原本是否就相邻即可。
可以去他的博客里看看http://blog.moe.cn.com/1351.htm
下面说一下我的离散化过程(也是一位学长教的)
例如区间[2,5]我们在处理时可以写成[2,6),之后用2 6,这两个数进行离散化操作,变成[1,2),因为线段树是对闭区间进行操作,所以在更新数据时改成[1,1]就好了,相当于把左区间整体右移了一位,所以上述第二种情况就可以避免了,这样操作的话需要注意颜色下放时退出递归的条件。
最后一个坑,n有可能等于0;

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<set>
using namespace std;
#define F(x,a,b) for (int x=a;x<=b;x++)
#define MAXN 20005
#define me(x) memset(x,0,sizeof(x))
struct p{int l,r;}re[20*MAXN],rel[20*MAXN];
struct pp{int l,r,val;}tree[20*MAXN];
set<int>a;
int b[20*MAXN];
int color[20*MAXN];
int ans;
void creatree(int i,int l,int r)
{
  tree[i].r=r;tree[i].l=l;tree[i].val=0;
  if (l==r) return;
  int mid=(l+r)>>1;
  creatree(i<<1,l,mid);
  creatree((i<<1)+1,mid+1,r);
}
void up(int i,int l,int r,int c)
{
   if (l==tree[i].l&&r==tree[i].r)
   {
      tree[i].val=c;
      return;
   }
   if (tree[i].val!=0)
   {
     tree[i<<1].val=tree[i].val;
     tree[(i<<1)+1].val=tree[i].val;
     tree[i].val=0;
   }
   int mid=(tree[i].l+tree[i].r)>>1;
   if (r<=mid) up(i<<1,l,r,c);
   if (l>mid) up((i<<1)+1,l,r,c);
   if (l<=mid&&r>mid) {up(i<<1,l,mid,c);up((i<<1)+1,mid+1,r,c);}
}
void _find(int i)
{
  if (tree[i].val!=0)
  {
    if (!color[tree[i].val])
    {
      ans++;
      color[tree[i].val]++;
    }
    return;
  }
  if (tree[i].l==tree[i].r) return;
  _find(i<<1);
  _find((i<<1)+1);
}
int _s(int p[],int len,int x)
{
  int l=0;int r=len;
  while (r-l>1)
  {
     int mid=(l+r)>>1;
     if (p[mid]>=x)
      r=mid;
     else l=mid;
  }
  return r;
}
int main()
{
  int T;
  scanf("%d",&T);
  while (T--)
  {
    int n; scanf("%d",&n);
    if (n==0) {printf("0\n");continue;}
    int cnt=0;
    a.clear();
    me(b);
    F(i,1,n)
    {
      scanf("%d%d",&re[i].l,&re[i].r);
      a.insert(re[i].l);a.insert(re[i].r+1);
    }
    set<int>::iterator it;cnt=0;
    for (it=a.begin();it!=a.end();it++)
    {
        b[++cnt]=*it;
    }
    F(i,1,n)
    {
      int p=_s(b,cnt,re[i].l);
      int q=_s(b,cnt,re[i].r+1);
      rel[i].l=p;
      rel[i].r=q-1;
    }
    me(color);
    ans=0;
    creatree(1,1,cnt-1);
    F(i,1,n)
    {
      up(1,rel[i].l,rel[i].r,i);
    }
    _find(1);
    printf("%d\n",ans);
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章