zoukankan      html  css  js  c++  java
  • poj2528(线段树+离散化)

    题目链接:https://vjudge.net/problem/POJ-2528

    题意:在区间[1,1e7]内染色,依次染n(<=1e4)中颜色,给出每种颜色染色的范围,可重叠,求最终有多少种颜色。

    思路:继续肝线段树。。被这题虐了一下午加一晚上QAQ。

       首先要想到离散化,因为区间为1e7,直接做的话时间空间都做不到。但因为是区间,这里不能简单的离散化,比如1、5离散化为1、2是有问题的,必须离散化为1,3,5; 还记得要先去重。

       其次是线段树,这道题是典型的线段树的题,直接对点操作的话复杂度很大,所以用线段树完成对区间的操作。线段树结点包括l(区间左端点)、r(区间右端点)、value(为0表示该区间没有颜色或有多种颜色,为>0表示对应的颜色编号)。

       最后进行一次询问即可,仅当区间的value>0时再判断颜色,并且用hash数组记录颜色i是否出现过。

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=10005;
    
    struct node{
        int l,r,value;
    }tr[16*maxn];
    
    int a[maxn][2],b[4*maxn],T,n,hash[maxn],ans;
    
    void build(int v,int l, int r){
        tr[v].l=l,tr[v].r=r,tr[v].value=0;
        if(l==r) return;
        int mid=(l+r)>>1;
        build(v<<1,l,mid);
        build(v<<1|1,mid+1,r);
    }
    
    void pushdown(int v){
        tr[v<<1].value=tr[v].value;
        tr[v<<1|1].value=tr[v].value;
        tr[v].value=0;
    }
    
    void update(int v,int l,int r,int k){
        if(l<=tr[v].l&&r>=tr[v].r){
            tr[v].value=k;
            return;
        }
        if(tr[v].value) pushdown(v);
        int mid=(tr[v].l+tr[v].r)>>1;
        if(l<=mid) update(v<<1,l,r,k);
        if(r>mid) update(v<<1|1,l,r,k);
    }
    
    void query(int v){
        if(tr[v].value){
            if(!hash[tr[v].value]){
                ++ans;
                hash[tr[v].value]=1;
            }
            return;
        }
        if(tr[v].l==tr[v].r) return;
        query(v<<1);
        query(v<<1|1);
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            memset(hash,0,sizeof(hash));
            ans=0;
            scanf("%d",&n);
            int cnt1=0;
            for(int i=1;i<=n;++i){
                scanf("%d%d",&a[i][0],&a[i][1]);
                b[++cnt1]=a[i][0];
                b[++cnt1]=a[i][1];
            }
            sort(b+1,b+cnt1+1);
            int cnt2=1;
            for(int i=2;i<=cnt1;++i)
                if(b[i]!=b[i-1]) b[++cnt2]=b[i];
            int t=cnt2;
            for(int i=2;i<=t;++i)
                if(b[i]-b[i-1]>1) b[++cnt2]=b[i-1]+1;
            sort(b+1,b+cnt2+1);
            build(1,1,cnt2);
            for(int i=1;i<=n;++i){
                int x=lower_bound(b+1,b+cnt2+1,a[i][0])-b;
                int y=lower_bound(b+1,b+cnt2+1,a[i][1])-b;
                update(1,x,y,i);
            }
            query(1);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    linux下,ssh服务安装和法git简单的使用方,整理实测。
    css+jquery实现标签浮动效果《前端随笔》
    java 学习随笔《时间篇》
    企业使用OKR管理绩效的三大好处
    绩效反馈评语:如何评估团队合作
    高绩效团队:使用 OKR 方法持续改进
    企业成功实践OKR的三个秘诀
    jsGen技术总结之:在Node.js中构建redis同步缓存
    财务数据可视化
    python3爬取上市公司基本数据
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10780522.html
Copyright © 2011-2022 走看看