POJ2528 Mayor's posters【线段树+lazy标志+离散化+hash+折半查找】

简介:
Problem: 2528   User: qq1203456195
Memory: 1120K   Time: 94MS
Language:C++   Result: Accepted
复制代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 11111
int hash[maxn];
int li[maxn],ri[maxn];
int X[maxn<<4];
int col[maxn<<4];//maxn张海报对应maxn<<1个边界,最多需要添加maxn<<1个辅助点,即的线段树要((maxn<<1)<<1)<<2个结点。
int cnt;

void PushDown(int rt)//lazy标志位下传
{
    if(col[rt]!=-1)
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        col[rt]=-1;
    }
}

void update(int L,int R,int C,int l,int r,int rt)
{
    int m=(l+r)>>1;
    if(L<=l&&r<=R)
    {
        col[rt]=C;
        return;
    }
    PushDown(rt);
    if (L<=m)    update(L,R,C,lson);
    if (m< R)    update(L,R,C,rson);

}
void query(int l,int r,int rt)
{
    int m=(l+r)>>1;
    if(col[rt]!=-1)
    {
        if(!hash[col[rt]])
            cnt++;
        hash[col[rt]]=1;
        return;
    }
    if(l==r)    return;
    query(lson);
    query(rson);

}
int Bin(int key,int len,int *x)//在长度为len的数组中二分查找key的位置
{
    int l=0,r=len;
    int m;
    while(l<=r)
    {
        m=(l+r)>>1;
        if(x[m]==key)    return m;
        if(x[m]<key)    l=m+1;
        else            r=m-1;
    }
    return -1;
}
int main()
{
    int i,m,n,p,cas,L,R,C;
    scanf("%d",&cas);
    while (cas--)
    {
        scanf("%d",&n);
        //读取数据,并构造待离散化数组X,离散化第一步
        p=0;
        for (i=0;i<n;i++)
        {
            scanf("%d%d",&li[i],&ri[i]);
            X[p++]=li[i];
            X[p++]=ri[i];
        }
        //将X内数据排序,离散化第二步(注意数据范围:x[0]...x[p-1])
        sort(X,X+p);
        //去掉X内重复值,离散化第三步
        /*从1开始,到p-1为止*/
        m=1;
        for (i=1;i<p;i++)
        {
            if(X[i]!=X[i-1])//如果不等,说明没有出现过,就保留;否则就丢弃。
                X[m++]=X[i];
        }
        /*难点!如果出现1,2,5,9这种数据,就改成1,2,5,6,9
        也就是说如果相邻数字间距大于1的话,在其中加上任意一个和相邻数字中的某个数字
        差值为1的数字
        */
        for (i=m-1;i>0;i--)
        {
            if(X[i]!=X[i-1]+1)
                X[m++]=X[i-1]+1;
        }
        sort(X,X+m);//(注意数据范围:x[0]...x[m-1])
        //离散化结束,只需建立叶子节点为m的线段树即可,X[m]的值就是输入的数据中的一个。
        //为了统计海报的个数,就需要海报的标记,而li,ri的下标就可以做海报的标记
        //创建线段树
        memset(col,-1,sizeof(col));
        for (i=0;i<n;i++)
        {
            L=Bin(li[i],m-1,X);
            R=Bin(ri[i],m-1,X);
            C=i;
            update(L,R,C,0,m,1);
        }
        //统计海报个数
        cnt=0;
        memset(hash,0,sizeof(hash));
        query(0,m,1);
        printf("%d\n",cnt);
    }
    return 0;
}
复制代码

 

本文转自ZH奶酪博客园博客,原文链接:http://www.cnblogs.com/CheeseZH/archive/2012/05/11/2496536.html,如需转载请自行联系原作者

相关文章
|
11月前
|
算法 C语言
OJ刷题:求俩个数组的交集(没学哈希表?快排双指针轻松搞定!)
OJ刷题:求俩个数组的交集(没学哈希表?快排双指针轻松搞定!)
|
11月前
【每日一题Day293】LC23合并K个升序链表 | K指针 堆排序 归并排序
【每日一题Day293】LC23合并K个升序链表 | K指针 堆排序 归并排序
55 0
|
11月前
【每日一题Day340】LC2251花期内花的数目 | 差分+哈希表+排序 排序+二分查找
【每日一题Day340】LC2251花期内花的数目 | 差分+哈希表+排序 排序+二分查找
46 0
|
11月前
|
存储
【每日一题Day132】LC23633合并相似的物品 | 哈希表 排序+双指针
【每日一题Day132】LC23633合并相似的物品 | 哈希表 排序+双指针
71 0
|
11月前
【每日一题Day163】LC2367算术三元组的数目 | 二分查找 哈希表
【每日一题Day163】LC2367算术三元组的数目 | 二分查找 哈希表
39 0
|
算法 Java
折半查找算法[二分查找法]算法的实现和解决整数溢出问题~
折半查找算法[二分查找法]算法的实现和解决整数溢出问题~
137 1
【Leetcode -1609.奇偶树 -1122.数组的相对排序】
【Leetcode -1609.奇偶树 -1122.数组的相对排序】
67 0
|
8月前
|
算法 索引
【算法】二分算法——山脉数组的峰顶索引
【算法】二分算法——山脉数组的峰顶索引
|
11月前
|
搜索推荐 算法 索引
【排序算法】深入解析快速排序(霍尔法&&三指针法&&挖坑法&&优化随机选key&&中位数法&&小区间法&&非递归版本)
【排序算法】深入解析快速排序(霍尔法&&三指针法&&挖坑法&&优化随机选key&&中位数法&&小区间法&&非递归版本)
288 4