POJ2528 线段树区间覆盖

本文探讨了一种优化方法,针对包含大量不同颜色元素的树状结构进行高效统计,特别关注如何在更新操作中减少计算量,并在最终统计结果时避免不必要的遍历整棵树的操作。

题意:在墙上贴海报 然后后一次贴上去的会覆盖上一次贴的 然后最后贴完之后求最后能够看见的有几张

解法:这一题很早就想写了 但是当我写了大量线段树反倒是觉得这个真的有什么优化也只是再插入的时候了 然后最后统计区间居然接近遍历了整棵树 这个使我困惑了很久 悲剧的是 这题并不需要pushup 这是真的 因为我们也没有什么办法统计出这个区间中的不同的颜色的个数和信息的 毕竟这可是有1w种颜色啊 

#include<cstdio>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 111111
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
int set[maxn<<2],ha[maxn],_l[maxn],_r[maxn];
int ans;
inline void down(int rt){
    if(set[rt]!=-1){
        set[ls]=set[rs]=set[rt];
        set[rt]=-1;
    }
}
inline void ins(int rt,int l,int r,int L,int R,int w){
    if(L<=l&&r<=R){
        set[rt]=w;return ;
    }down(rt);
    if(L<=mid)ins(ls,l,mid,L,R,w);
    if(mid<R)ins(rs,mid+1,r,L,R,w);
}
inline void query(int rt,int l,int r){
    if(set[rt]!=-1){
        if(!ha[set[rt]])ans++;
        ha[set[rt]]++;
        return ;
    }
    if(l==r)return ;
    query(ls,l,mid);
    query(rs,mid+1,r);
}
int _,x[maxn],n,cnt,all,fi[maxn];
int main(){
    scanf("%d",&_);
    while(_--){
        scanf("%d",&n);all=cnt=0;
        for(int i=0;i<n;++i){
            scanf("%d%d",&_l[i],&_r[i]);
            x[cnt++]=_l[i];x[cnt++]=_r[i];
        }
        sort(x,x+cnt);
        fi[++all]=x[0];
        for(int i=1;i<cnt;++i){
//            printf("%d %d\n",fi[all],x[i]);
            if(fi[all]!=x[i]){
                if(x[i]-fi[all]>1){
                    fi[++all]=x[i]-1;
                }
                fi[++all]=x[i];
            }
        }

        memset(ha,0,sizeof ha);
        memset(set,-1,sizeof set);
        for(int i=0;i<n;++i){
            int ll=(int)(lower_bound(fi+1,fi+1+all,_l[i])-fi);
            int rr=(int)(lower_bound(fi+1,fi+1+all,_r[i])-fi);
            ins(1,1,all,ll,rr,i+1);
        }ans=0;
        query(1,1,all);
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值