• 【NOIP模拟赛】天神下凡 动态开点线段树


    这些圆一定是在同一水平面上的,由于他们没有相交,因此我们发现他们每个人与外界关系可以分为,1.存在并圈圈 2.存在圈圈并被割,因此我们把所有的圆都加1,把被割的在加1,就可以啦,因此我们开一个线段树,维护一段区间有没有被全部覆盖

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #define R register
    #define MAXN 300000
    using namespace std;
    typedef unsigned long UI;
    struct O
    {
        UI x,r;
    }o[MAXN+10];
    int n;
    int comp(const O a,const O b)
    {
        return a.r<b.r;
    }
    struct Seg_Tree
    {
        bool cover;
        UI l,r,mid;
        Seg_Tree *ch[2];
     
    }*root;
    inline Seg_Tree *New(UI l,UI r)
    {
        R Seg_Tree *p=new Seg_Tree;
        p->cover=0;
        p->l=l;
        p->r=r;
        p->mid=((long long)l+r)>>1;
        p->ch[1]=p->ch[0]=NULL;
        return p;
    }
    bool query(Seg_Tree *p,UI l,UI r)
    {
        if(p->cover)return 1;
        if(l<=p->l&&p->r<=r)return p->cover;
        R bool ans=1;
        if(l<=p->mid)
        {
           if(!p->ch[0])return 0;
           else ans&=query(p->ch[0],l,r);
        }
        if(p->mid<r)
        {
           if(!p->ch[1])return 0;
           else ans&=query(p->ch[1],l,r);
        }
        return ans;
    }
    void ins(Seg_Tree *p,UI l,UI r)
    {
        if(p->cover)return;
        if(l<=p->l&&p->r<=r)
        {
            p->cover=1;
            return;
        }
        if(l<=p->mid)
        {
           if(!p->ch[0]) p->ch[0]=New(p->l,p->mid);
           ins(p->ch[0],l,r);
        }
        if(p->mid<r)
        {
           if(!p->ch[1]) p->ch[1]=New(p->mid+1,p->r);
           ins(p->ch[1],l,r);
        }
        if(p->ch[0]&&p->ch[1])p->cover=p->ch[0]->cover&p->ch[1]->cover;
    }
    inline void Init()
    {
        scanf("%d",&n);
        for(R int i=1;i<=n;i++)
        {
            R int x,r;
            scanf("%d%d",&x,&r);
            o[i].x=(long long)x+2000000005;
            o[i].r=r;
        }
        sort(o+1,o+n+1,comp);
        root=New(1,4000000010LL);
    }
    inline void work()
    {
        R int ans=1;
        for(int i=1;i<=n;i++)
        {
            ++ans;
            if(query(root,o[i].x-o[i].r,o[i].x+o[i].r))++ans;
            ins(root,o[i].x-o[i].r,o[i].x+o[i].r);
        }
        printf("%d",ans);
    }
    int main()
    {
        Init();
        work();
        return 0;
    }
  • 相关阅读:
    [LeetCode 220.] 存在重复元素 III
    C++ 构造函数 & 析构函数
    [LeetCode 891.] 子序列宽度之和【hard】
    [LeetCode 447.] Number of Boomerangs
    HJ93 数组分组
    HJ77 火车进站
    [LeetCode 338.] 比特位计数
    线段树
    大数量问题的一般解决方法
    字典树
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7260373.html
Copyright © 2020-2023  润新知