zoukankan      html  css  js  c++  java
  • 2016级算法第二次上机-A.画个圈圈诅咒你

    890 画个圈圈诅咒你

    思路

    简单题。题目中的圆并没有什么实际作用,简化成线段重合问题会更好理解些。

    暴力解法:使用双重for循环会T到想哭,记住最直接的方法一般是过不了题的。

    解法一:二分查找。空间较小,时间更长。

    把圆相离的问题转换为线段相交的问题,按先起点后终点的顺序升序排列这些圆(线段)。对于每条线段,向右找到第一条起点比这条线段终点大的线段,然后后面的线段都会满足要求,这里用二分去找。具体参考参考代码一。

    解法二:线性查找。时间更短,空间更大。

    同样是把圆相离的问题转换为线段的相交问题,把所有圆的左点和右点记录下来,并标记他们是左还是右,点的数量是圆的数量的两倍。排序:按所有点的位置排,如果点位置一样,则左边点优先(重要)。从头到尾遍历一次,用一变量(初始值为n)记录右边有多少个圆的左点,遇到左点时变量减1,遇到右点时用答案加上当前变量值,即是此圆右边与之相离的数量(左边的不须计算否则会产生重复)。具体参考参考代码二。

    分析

    两种方法都需要排序,排序时间 (O(NlogN))

    查找时间:解法一是 (O(NlogN)),解法二是 (O(N))

    参考代码一

    //
    // Created by AlvinZH on 2017/10/24.
    // Copyright (c) AlvinZH. All rights reserved.
    //
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    int n, x, r;
    
    struct Circle {
        int left, right;
    
        bool operator < (const Circle a) const {
            if(left == a.left) return right < a.right;//其次右端
            return left < a.left;//左端优先
        }
    }C[50005];
    
    //二分查找右边最近的圆
    int find(int l, int r, int x)
    {
        int m;
        while(l <= r)
        {
            m = (l + r) >> 1;
            if(C[m].left < x) l = m + 1;
            else if(C[m].left >= x) r = m - 1;
        }
        return l;
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i = 0; i < n; ++i) {
                scanf("%d %d", &x, &r);
                C[i].left = x - r;
                C[i].right = x + r;
            }
            sort(C, C+n);
    
            int ans=0;
            for(int i = 0; i < n-1; i++) {
                ans += n - find(i+1, n-1, C[i].right+1);
            }
            printf("%d
    ", ans);
        }
    }
    

    参考代码二

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    int n, x, r;
    
    struct Node {
        int x;//位置
        int isR;//标记左右
    
        bool operator < (const Node n) const {
            if(x < n.x) return true;
            else if(x == n.x && isR == 0) return true;
            return false;
        }
    }N[100010];
    
    int main()
    {
        while(~scanf("%d", &n))
        {
            int num = 0;
            for (int i = 0; i < n; ++i) {
                scanf("%d %d", &x, &r);
                N[num].x = x - r;
                N[num].isR = 0;
                num++;
                N[num].x = x + r;
                N[num].isR = 1;
                num++;
            }
            sort(N, N+num);
    
            int ans = 0;
            int sum = n;
            for (int i = 0; i < num; ++i) {
                if(N[i].isR == 0) sum--;
                else ans += sum;
            }
            printf("%d
    ", ans);
        }
    }
    
  • 相关阅读:
    周末之个人杂想(十三)
    PowerTip of the DaySorting Multiple Properties
    PowerTip of the DayCreate Remoting Solutions
    PowerTip of the DayAdd Help to Your Functions
    PowerTip of the DayAcessing Function Parameters by Type
    PowerTip of the DayReplace Text in Files
    PowerTip of the DayAdding Extra Information
    PowerTip of the DayPrinting Results
    Win7下IIS 7.5配置SSAS(2008)远程访问
    PowerTip of the DayOpening Current Folder in Explorer
  • 原文地址:https://www.cnblogs.com/AlvinZH/p/7761354.html
Copyright © 2011-2022 走看看