poj 2528 线段树+离散化

 

题目链接:http://poj.org/problem?id=2528

 

 

题意:

    在墙上贴海报,输入n(1<=n<=10000),表示n张海报,后n行输入 两整数l,r  ( 1<= l, r<= 1e9 ),表示海报从编号为l的石头一直贴到编号为r的石头,输入顺序即为粘贴顺序。问n张贴完之后,还能看到多少张海报。

 

思路:

      显然区间操作,很容易联想到线段树操作,只不过区间 l,r 最大范围可达1e9,直接建树,内存必爆。   那么就需要避开1e9的数据,进行离散化,将区间变成(1到n)

 

 

      至于如何离散化,原理是映射+压缩。 

 

  

样例:
1
5 1 4 2 6 8 10 3 4 7 10

 

 1 4 2  6 8 10 3 4 7 10
排序+去重   :    1  2  3  4  6  7  8  10    存入x数组
对上数组进行编号  1  2  3  4  5  6  7  8     即x【1】=1    x【2】=2    x【5】=6    x【8】=10    (即对原数组进行压缩)

 

本题特殊的一点:需要中间插值

 

 

设一个样例

3
1 10
1 3
5 10


进行离散化:
        1    3    5    10
编号:
        1    2    3    4


依次贴海报
        1    10    对应的是  1  4
        1    3       对应的是  1    2
        5     10                   3    4

显然 依次贴【1,4】   【1,2】  【3,4】
       显然第一张海报【1,4】被覆盖,即答案为:2

但是实际答案为3。


至于如何解决:

   中间插值 (即对两个相邻数字,相差大于1的插入某值)

进行中间插值离散化:
        1  2  3   4   5   6  10
编号:
        1  2  3   4   5   6   7


这时答案为3

 

 

AC代码:

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#include<map> 
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Mem0(x) memset(x,0,sizeof(x))
#define Mem1(x) memset(x,-1,sizeof(x))
#define MemX(x) memset(x,0x3f,sizeof(x))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f;
const double pi=acos(-1.0);

const int MAXN=10010;
struct Tree{
    int l,r,lazy;
}tree[MAXN<<4];

struct s{
    int l,r;
}a[MAXN<<4];
int x[MAXN<<4];
bool hash[MAXN<<4];
int n,ans;

void pushdown(int rt)
{
    tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy;
    tree[rt].lazy=-1;
}
void update(int left,int right,int c,int l,int r,int rt)
{
    if (l>=left&&r<=right){
        tree[rt].lazy=c;
        return ;
    }
    if (tree[rt].lazy!=-1)
        pushdown(rt);
    int mid=(l+r)>>1;
    if (mid>=left)
        update(left,right,c,l,mid,rt<<1);
    if (mid<right)
        update(left,right,c,mid+1,r,rt<<1|1);
    return ;
}

void query(int l,int r,int rt)
{
    if (l==r){
        if (!hash[tree[rt].lazy]){
            ans++;
            hash[tree[rt].lazy]=true;
        }
        return ;
    }
    if (tree[rt].lazy!=-1)
        pushdown(rt);
    int mid=(l+r)>>1;
    query(l,mid,rt<<1);
    query(mid+1,r,rt<<1|1);
} 
int main()
{
    int n,t;
    scanf("%d",&t);
    while (t--){
        memset(tree,-1,sizeof(tree));
        memset(hash,false,sizeof(hash));
        int cnt=0;
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            scanf("%d%d",&a[i].l,&a[i].r);
            x[++cnt]=a[i].l;
            x[++cnt]=a[i].r;
        }
        sort(x+1,x+cnt+1);
        int size=unique(x+1,x+cnt+1)-x-1;  //离散化+去重 
        for (int i=size;i>1;i--){         //中间增值 
            if (x[i]-x[i-1]>1)    
                x[++size]=x[i]-1;
        }
        sort(x+1,x+size+1);
        for (int i=1;i<=n;i++){
            int l=lower_bound(x+1,x+size+1,a[i].l)-x;   //二分查找的内库函数
            int r=lower_bound(x+1,x+size+1,a[i].r)-x;
            update(l,r,i,1,size,1);
        }
        ans=0;
        query(1,size,1);
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2019-07-31 23:25  生活待我如初恋  阅读(183)  评论(0编辑  收藏  举报