POJ 2528 Mayor's posters (离散化和线段树使用)

还是做了线段树的题目,玩了两天也要继续看看题目了。之前就有看离散化的概念,大家可以去百度百科一下,简单转载一个例子

离散化 的大概思路 : 比如说给你一组 数据 1 4 1000 100000, 如果直接
开线段, 显然是浪费, 那么我们只要 进行 映射 :
1                   1
4                   2
1000              3
100000          4
接下来 我们只要对 1 2 3 4 建立线段树就行了 只需要[1,4]的区间。

差不多就是这样了,这样就可以大大减少使用的内存空间。

这道题目的数据范围非常大1 <= li <= ri <= 10000000;直接开肯定爆掉的,而且光建树就浪费非常多的时间了,所以做离散化映射。因为1 <= n <= 10000,所以建树开四倍大空间就行,又以为一个输入数据两个点,所以是八倍空间。本题重点是离散化的使用,记得之前比赛题目就是这题,那时候还不会线段树,就无限尝试一直WA,现在终于解决了。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include<algorithm>
using namespace std;
struct NODE
{
    int l,r,val;
}tree[80005];
struct node
{
 int l,r;
}num[10001];
bool vis[10001];
int ans,lag[20001],n;
void build(int l,int r,int index)   //建树
{
    tree[index].l=l;
    tree[index].r=r;
 tree[index].val=0;
    if(l==r)
        return;
 int mid=(l+r)/2;
 build(l,mid,2*index);
 build(mid+1,r,2*index+1);
}
int find(int x)              //二分查找对应点
{
 int l=0,r=n-1;
 while(l<=r)
 {
  int mid=(l+r)/2;
  if(lag[mid]==x)
   return mid+1;
  else
   if(lag[mid]>x)
   r=mid-1;
  else
   l=mid+1;
 }
}
void update(int l,int r,int index,int c)         //更新线段树,标记属于哪个宣传
{
    if(l==tree[index].l && r==tree[index].r)
    {
        tree[index].val=c;
        return;
    }
 if(tree[index].val>-1)
 {
  tree[2*index].val=tree[2*index+1].val=tree[index].val;
  tree[index].val=-1;
 }
 int mid=(tree[index].l+tree[index].r)/2;
    if(mid>=l && mid+1<=r)
 {
  update(l,mid,2*index,c);
        update(mid+1,r,2*index+1,c);
 }
    else
  if(r<=mid)
        update(l,r,2*index,c);
    else
  if(l>=mid+1)
        update(l,r,2*index+1,c);
}
void query(int l,int r,int index)            
{
    if(tree[index].val>-1)           //询问的核心     满足条件的情况
 {
  int tc=tree[index].val;
  if(!vis[tc] && tc)
  {
   vis[tc]=1;
   ans++;
  }
  return;
 }
    int mid=(tree[index].l+tree[index].r)/2;
    if(l<=mid && r>=mid+1)
 {
  query(l,mid,2*index);
  query(mid+1,r,2*index+1);
 }
    else
  if(r<=mid)
        query(l,r,2*index);
    else
  if(l>=mid+1)
        query(l,r,2*index+1);
}
int main()
{
    int i,t,N,pre,l,r;
    scanf("%d",&t);
 while(t--)
 {
  memset(vis,0,sizeof(vis));
  scanf("%d",&N);
  for(i=0;i<N;i++)               //输入数据做映射
  {
   scanf("%d%d",&num[i].l,&num[i].r);
   lag[2*i]=num[i].l;
   lag[2*i+1]=num[i].r;
  }
  sort(lag,lag+2*N);
  n=pre=0;
  for(i=0;i<2*N;i++)      //去除相同数据
  {
   if(lag[i]!=pre)
   {
    pre=lag[i];
    lag[n++]=lag[i];
   }
  }
  build(1,n,1);
  for(i=0;i<N;i++)         //开始一个个点的更新
  {
   l=find(num[i].l);
   r=find(num[i].r);
   update(l,r,1,i+1);
  }
  ans=0;
  query(1,n,1);
  printf("%d\n",ans);
 }
 return 0;
}

posted @ 2012-02-04 14:36  Lxsec  阅读(241)  评论(0)    收藏  举报