• ACM学习历程——NOJ1113 Game I(贪心 || 线段树)


    Description

    尼克发明了这样一个游戏:在一个坐标轴上,有一些圆,这些圆的圆心都在x轴上,现在给定一个x轴上的点,保证该点没有在这些圆内(以及圆上),尼克可以以这个点为圆心做任意大小的圆,他想知道自己做多可以与多少个给定的圆相交(相切也算,包含不算)。

    Input

    输入有多组数据 输入到文件尾

    每一组数据有一个整数n(1<=n<=100000),表示总共有n个圆。

    接下是n行,每行两个整数xi,ri表示该圆的圆心坐标和半径。

    接下来一行为一个整数x,表示尼克选取点的位置。

    x xi的范围[-10^9,10^9]  ri的范围[1,10^9]

    总共有最多10组数据。

    Output

    每组数据输出一行,表示尼克最多可以覆盖多少个圆。

    Sample Input

    2
    1 2
    2 1
    4

    Sample Output

    2

     这个题目条件转换一下就是满足|r-d| <= R <= r+d的R就能与r半径的圆相交,其中d是两圆圆心的距离。

    这样就变成了区间增值,然后查询区间中的最大值。

    首先想到的是线段树,复杂度是O(2n*log(2n))。不过由于半径范围的值是离散的,所以采用map进行映射,使其连续。不过AC用时500ms左右。

    然后发现其实直接处理后直接贪心就行。将所有区间的左右端点排序,排序时需要保存标记,用于记录这个端点是某个区间的左端点还是右端点。然后就是扫一遍,对于是左端点的自然值加一,对于右端点的自然值减一,然后贪心过程中的最大值。AC用时85ms左右。


    贪心代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <map>
    #include <set>
    #include <algorithm>
    #define LL long long
    
    using namespace std;
    
    struct node
    {
        LL index;
        bool isleft;
    }ind[200005];
    
    int n, ans;
    LL x[100005], r[100005], xx;
    
    bool cmp(node a, node b)
    {
        return a.index < b.index;
    }
    
    LL Abs(LL aa)
    {
        if (aa < 0)
            return -aa;
        else
            return aa;
    }
    
    void Init()
    {
        LL d, Left, Right;
        for (int i = 0; i < n; ++i)
        {
            d = Abs(x[i]-xx);
            Left = Abs(r[i]-d);
            Right = r[i]+d;
            ind[i<<1].index = Left;
            ind[i<<1].isleft = true;
            ind[i<<1|1].index = Right;
            ind[i<<1|1].isleft = false;
        }
        sort(ind, ind+2*n, cmp);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        while (scanf("%d", &n) != EOF)
        {
            for (int i = 0; i < n; ++i)
            {
                scanf("%lld%lld", &x[i], &r[i]);
            }
            scanf("%lld", &xx);
            Init();
            int len = 2*n;
            int now = 0;
            ans = 0;
            for (int i = 0; i < len; ++i)
            {
                if (ind[i].isleft)
                    now++;
                else
                    now--;
                ans = max(ans, now);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }

    线段树代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <map>
    #include <set>
    #include <algorithm>
    #define LL long long
    
    using namespace std;
    
    //线段树
    //区间每点增值,求区间最值
    const int maxn = 100005;
    struct node
    {
        int lt, rt;
        int val, add;
    }tree[8*maxn];
    
    //向下更新
    void PushDown(int id)
    {
        if (tree[id].add != 0)
        {
            tree[id<<1].add += tree[id].add;
            tree[id<<1].val += tree[id].add;
            tree[id<<1|1].add += tree[id].add;
            tree[id<<1|1].val += tree[id].add;
            tree[id].add = 0;
        }
    }
    
    //向上更新
    void PushUp(int id)
    {
        tree[id].val = max(tree[id<<1].val, tree[id<<1|1].val);
    }
    
    //建立线段树
    void Build(int lt, int rt, int id)
    {
        tree[id].lt = lt;
        tree[id].rt = rt;
        tree[id].val = 0;//每段的初值,根据题目要求
        tree[id].add = 0;
        if (lt == rt)
        {
            //tree[id].add = ??;
            return;
        }
        int mid = (lt + rt) >> 1;
        Build(lt, mid, id<<1);
        Build(mid+1, rt, id<<1|1);
        //PushUp(id);
    }
    
    //增加区间内每个点固定的值
    void Add(int lt, int rt, int id, int pls)
    {
        if (lt <= tree[id].lt && rt >= tree[id].rt)
        {
            tree[id].add += pls;
            tree[id].val += pls;
            return;
        }
        PushDown(id);
        int mid = (tree[id].lt + tree[id].rt) >> 1;
        if (lt <= mid)
            Add(lt, rt, id<<1, pls);
        if (rt > mid)
            Add(lt, rt, id<<1|1, pls);
        PushUp(id);
    }
    
    //查询某段区间内的zuizhi
    int Query(int lt, int rt, int id)
    {
        if (lt <= tree[id].lt && rt >= tree[id].rt)
            return tree[id].val;
        PushDown(id);
        int mid = (tree[id].lt + tree[id].rt) >> 1;
        if (rt <= mid)
            return Query(lt, rt, id<<1);
        if (lt > mid)
            return Query(lt, rt, id<<1|1);
        return max(Query(lt, rt, id<<1), Query(lt, rt, id<<1|1));
    }
    
    
    int n, cnt;
    LL x[100005], r[100005], ind[200005], xx;
    LL Left[100005], Right[100005];
    map <LL, int> id;
    
    bool cmp(LL a, LL b)
    {
        return a < b;
    }
    
    LL Abs(LL aa)
    {
        if (aa < 0)
            return -aa;
        else
            return aa;
    }
    
    void Init()
    {
        id.clear();
        LL d;
        for (int i = 0; i < n; ++i)
        {
            d = Abs(x[i]-xx);
            Left[i] = Abs(r[i]-d);
            Right[i] = r[i]+d;
            ind[i<<1] = Left[i];
            ind[i<<1|1] = Right[i];
        }
        sort(ind, ind+2*n, cmp);
        int len = 2*n;
        cnt = 1;
        for (int i = 0; i < len; ++i)
        {
            if (i == 0)
            {
                id[ind[0]] = 1;
                continue;
            }
            if (ind[i] != ind[i-1])
            {
                id[ind[i]] = ++cnt;
            }
        }
        Build(1, cnt, 1);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        while (scanf("%d", &n) != EOF)
        {
            for (int i = 0; i < n; ++i)
            {
                scanf("%lld%lld", &x[i], &r[i]);
            }
            scanf("%lld", &xx);
            Init();
            for (int i = 0; i < n; ++i)
            {
                Add(id[Left[i]], id[Right[i]], 1, 1);
            }
            printf("%d
    ", Query(1, cnt, 1));
        }
        return 0;
    }
  • 相关阅读:
    PyQt作品 – PingTester – 多点Ping测试工具
    关于和技术人员交流的一二三
    Pyjamas Python Javascript Compiler, Desktop Widget Set and RIA Web Framework
    Hybrid Qt applications with PySide and Django
    pyjamas build AJAX apps in Python (like Google did for Java)
    PyQt 维基百科,自由的百科全书
    InfoQ:请问为什么仍要选择Java来处理后端的工作?
    Eric+PyQt打造完美的Python集成开发环境
    python select module select method introduce
    GUI Programming with Python: QT Edition
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4463613.html
Copyright © 2020-2023  润新知