poj2528贴海报(线段树离散化)

//poj2528贴海报(线段树离散化)
#include
#include
#include
#include
using namespace std;
const int maxn=100005; //要开10倍的数组,否则RE
bool hash[maxn];
int li[maxn],ri[maxn];
int cov[maxn<<4];
int a[maxn*3];
int cnt;
int BinSea(int key,int n) //二分查找所在的编号即离散后的位置号
{
    int l=0,r=n-1;
    while(l<=r){
        int mid=(l+r)/2;
        if(a[mid]==key) return mid;
        else if(a[mid]=r){
        cov[p]=c;
        return;
    }
    Pushdown(p);
    int mid=(l+r)/2;
    if(x<=mid) Update(p<<1,l,mid,x,y,c);
    if(y>mid) Update(p<<1|1,mid+1,r,x,y,c);

}

void  Query(int p,int l,int r) //遍历每个区间的颜色
{
    if(cov[p]!=-1){
        if(!hash[cov[p]]){
            //cout<0;i--) //距离大于1的点之间加一个数
        {
            if((a[i]-a[i-1])>1) a[h++]=a[i-1]+1;
        }
        sort(a,a+h);
        memset(cov,-1,sizeof(cov));//初始标记为-1
        for(int i=0;i
int binsea(int key,int n){
    int l=0,h=r-1;
    while(l<=r){
        int mid=(h+l)>>1;
        if(a[mid]==key) return mid;
        if(a[mid>key]) l=mid+1;
        else if(a[mid]<=key) r=mid-1;
    }
    return -1;
}
void down(int rt){
    if(lazy[rt]!=-1){
        lazr[rt<<1]=lazy[rt<<1|1]=laz[rt];
        lazy[rt]=-1;
    }
}
void update(int rt,int l,int r,int x,int y,int c){// Update(1,0,h-1,l,r,i); c是颜色种类
    if(x<=l&&r<=y){//[l,r]属于[x,y]区间  覆盖掉[l,r]区间  [x,y]是题目给的
        lazy[rt]=c;return;
    }
    down(rt);
       int mid=(l+r)/2;  
    if(x<=mid) Update(p<<1,l,mid,x,y,c);  
    if(y>mid) Update(p<<1|1,mid+1,r,x,y,c);  
}
void query(int rt,int l,int r){//query(1,0,h-1)
    if(lazy[rt]!=-1){
        if(hash[lazy[rt]]==false){//初始值是false  避免重复计数
            cnt++;
            hash[lazy[rt]]==true;
        }
        return;
    }
    if(l==r) return;
    int mid=(l+r)/2;  
    Query(p<<1,l,mid);  
    Query(p<<1|1,mid+1,r); 
    
}

这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到10000000,而最多只有10000个点,如果直接建树的话太过于空旷。把这些区间的左右节点一一对应,最多有4×10000个点,远小于之前的10000000,而且区间之间的对应关系也不会改变。

举个例子: 
区间:[2,6],[4,8],[6,10] 
我们进行下面对应: 
2 4 6 8 10 
1 2 3 4 5 
则原区间变为[1,3],[2,4],[3,5]。可以发现它们之间的覆盖关系并没有改变,但是却紧凑了很多。 
但是注意对应后,应该有一个去重的操作,防止出错。

还有一点去需要注意,区间的对应稍不注意会出现颜色丢失的情况,如下: 
[1,10],–[1,4],–[6,10] 
当我们手工模拟会发现,我们只是对1,4,6,10,进行了对应,即1,2,3,4,原集合中的4,6被视为了相邻元素,所以5处的颜色丢失,最终得到了错误的结果。 
为了防止发生这种情况我们进行插值,在两个不相邻的节点间插入无关值,但是能有效的避免这种情况。


你可能感兴趣的:(ACM,机试,练级)