zoukankan      html  css  js  c++  java
  • Mayor's posters---poj2528线段树、离散化

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

    题意:有n张海报要贴,每张需要用的区间为L到R,后面的可以贴在之前的上面,就是吧之前的挡住,求最后我们能看到几张海报;

    我们可以倒着处理,因为最后贴的我们是能看到的;如果区间被贴过了result不加,没有贴过就+1并标记一下;

    由于数据范围太大所以用线段树

    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    #define N 10100
    #define Lson r<<1
    #define Rson r<<1|1
    
    struct Post
    {
        int L,R;
    }p[N];
    
    struct SegTree
    {
        int L, R, isCover;
        int Mid()
        {
            return (L+R)/2;
        }
    }a[N*16];
    
    int Hash[4*N];
    
    void Up(int r)
    {
        if(a[r].L!=a[r].R)
            if(a[Lson].isCover==1 && a[Rson].isCover==1)//向上更新,如果左右子树都被覆盖,那么他也会被覆盖
                a[r].isCover = 1;
    }
    
    void BuildSegTree(int r, int L, int R)
    {
        a[r].isCover = 0;
        a[r].L = L; a[r].R = R;
        if(L == R)
            return ;
        BuildSegTree(Lson, L, a[r].Mid());
        BuildSegTree(Rson, a[r].Mid()+1, R);
    }
    int judge(int r, int L, int R)
    {
        if(a[r].isCover==1)
            return 0;//被覆盖返回0;
        if(a[r].R == R && a[r].L == L)
        {
            a[r].isCover = 1;
            return 1;
        }
        int ans;
        if(L>a[r].Mid())
            ans = judge(Rson, L, R);
        else if(R<=a[r].Mid())
            ans = judge(Lson, L, R);
        else
        {
            int ans1 = judge(Lson, L, a[r].Mid());
            int ans2 = judge(Rson, a[r].Mid()+1, R);
            ans = ans1 | ans2;//只要有一个没被覆盖就说明能贴;
        }
        Up(r);
        return ans;
    }
    int main()
    {
        int T, n, k;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            k=0;
            for(int i=1; i<=n; i++)
            {
                scanf("%d%d", &p[i].L, &p[i].R);
                Hash[k++]=p[i].L-1;//防止出现离散化后原本不相邻的数变成相邻的了
                Hash[k++]=p[i].L;
                Hash[k++]=p[i].R+1;
                Hash[k++]=p[i].R;
            }
            sort(Hash, Hash+k);
            int len = unique(Hash, Hash+k) - Hash;
            BuildSegTree(1, 1, len);
            int result = 0;
            for(int i=n; i>0; i--)
            {
                int L = lower_bound(Hash, Hash+len, p[i].L) - Hash;
                int R = lower_bound(Hash, Hash+len, p[i].R) - Hash;
    
                int ans=judge(1, L, R);
                if(ans == 1)
                    result++;
            }
            printf("%d
    ", result);
        }
        return 0;
    }
    View Code

     过了那么久再写一遍

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<stack>
    using namespace std;
    
    #define INF 0xfffffff
    #define N 100050
    #define Lson r<<1
    #define Rson r<<1|1
    
    struct SegmentTree
    {
        int L, R;
        bool IsCover;///判断此区间是否被覆盖;
    
        int Mid() { return (L+R)>>1;}
        int len() { return R-L+1; }
    
    } a[N<<2];
    
    void Build(int r, int L, int R)
    {
        a[r].L = L, a[r].R = R;
        a[r].IsCover = false;
    
        if(L == R) return;
    
        Build(Lson, L, a[r].Mid());
        Build(Rson, a[r].Mid()+1, R);
    
        a[r].IsCover = a[Lson].IsCover && a[Rson].IsCover;
    }
    
    int Query(int r, int L, int R)
    {
        int ans;
        if(a[r].IsCover == true)
            a[Lson].IsCover = a[Rson].IsCover = a[r].IsCover;
    
        if(a[r].IsCover == true)///被覆盖了,返回0;
            return 0;
        if(a[r].L == L && a[r].R == R)///没被覆盖,把它覆盖,并返回1;
        {
            a[r].IsCover = true;
            return 1;
        }
    
        if(R<=a[r].Mid())
            ans = Query(Lson, L, R);
        else if(L>a[r].Mid())
            ans = Query(Rson, L, R);
        else
        {
            int ans1 = Query(Lson, L, a[r].Mid());
            int ans2 = Query(Rson, a[r].Mid()+1, R);
            ans =  (ans1 || ans2);///只要有一边没被覆盖就说明能贴;
        }
        a[r].IsCover = a[Lson].IsCover && a[Rson].IsCover;///向上更新,因为有了这个更新所以不能在上面直接返回结果;
        return ans;
    }
    
    struct node
    {
        int L, R;
    }p[N];
    
    int Hash[N*4], cnt;
    
    int main()
    {
        int T, n,  L, R;
        scanf("%d", &T);
        while(T--)
        {
            cnt = 0;
            scanf("%d", &n);
            for(int i=1; i<=n; i++)
            {
                scanf("%d %d", &p[i].L, &p[i].R);
                Hash[cnt++] = p[i].L;   Hash[cnt++] = p[i].R;
                Hash[cnt++] = p[i].L-1; Hash[cnt++] = p[i].R+1;
                ///加上左右边界是为了防止出现本身没有相连的,而离散化之后相连的情况;
            }
            sort(Hash, Hash+cnt);
            cnt = unique(Hash, Hash+cnt)-Hash;
    
            Build(1, 1, cnt);
    
            int ans = 0;
    
            for(int i=n; i>=1; i--)
            {
                L = lower_bound(Hash, Hash+cnt, p[i].L) - Hash;
                R = lower_bound(Hash, Hash+cnt, p[i].R) - Hash;
                ans += Query(1, L, R);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    登录界面
    冲刺一阶段(5月9日)-个人总结07
    冲刺一阶段(5月8日)-个人总结06
    冲刺一阶段(5月7日)-个人总结05
    冲刺一阶段(5月6日)-个人总结04
    冲刺一阶段(5月5日)-个人总结03
    冲刺一阶段(5月4日)-个人总结02
    第一阶段冲刺--个人总结01(忘记发了)
    软件需求分析(补发)
    第八周工作进程表
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4691126.html
Copyright © 2011-2022 走看看