Gym 101480I Ice Igloos(思维乱搞)题解

题意:给个最多500 * 500的平面,有半径最多不为1的n个圆,现在给你1e5条线段,问你每条线段和几个圆相交,时限10s

思路:

因为半径<1,那么我其实搜索的范围只要在线段附近就好了。x1 == x2 或者 y1 == y2这个很好理解,不解释。如果是斜率> 0的,那么对于任意的x (x1 <=  x < x2),那我的范围就是floor(y)~ceil(y + 1),另一种斜率同理。然后我去数每一个格子有没有圆,能不能碰到我线段就行了。每个格子数完标记一下。可以偷个懒,标记为p,然后每次判是不是p,这样就省了每次都初始化。

题解虽然说最好规避sqrt,不过好像精度影响不大。

毒瘤的是输入,x1 > x2,y1 > y2。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 500 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
double r[maxn][maxn], k;
int vis[maxn][maxn];
double a, b;
double getY(double x){
    return k * (x - a) + b;
}
bool check(double x, double y, double R){
    double dis = fabs(k * x - k * a + b - y) / sqrt(k * k + 1);
    if(dis <= R) return true;
    return false;
}
int main(){
    int n;
    int x1, y1, x2, y2, ans;
    memset(r, 0, sizeof(r));
    memset(vis, 0, sizeof(vis));
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        int u, v;
        double l;
        scanf("%d%d%lf", &u, &v, &l);
        r[u][v] = l;
    }
    scanf("%d", &n);
    for(int p = 1; p <= n; p++){
        int up, down;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        a = x1, b = y1;
        ans = 0;
        k = ((double)(y2 - y1)) / ((double)(x2 - x1));
        if(x1 == x2){
            if(y1 > y2) swap(y1, y2);
            for(int i = y1; i <= y2; i++)
                if(r[x1][i] != 0) ans++;
        }
        else if(y1 == y2){
            if(x1 > x2) swap(x1, x2);
            for(int i = x1; i <= x2; i++)
                if(r[i][y1] != 0) ans++;
        }
        else{
            if(x1 > x2){
                swap(x1, x2);
                swap(y1, y2);
            }
            if(k > 0){
                for(int i = x1; i < x2; i++){
                    up = (int)ceil(getY(i + 1));
                    down = (int)floor(getY(i));
                    if(i == x1) down = y1;
                    if(i == x2 - 1) up = y2;
                    for(int j = down; j <= up; j++){
                        if(r[i][j] > 0 && vis[i][j] != p && check(i, j, r[i][j])){
                            vis[i][j] = p;
                            ans++;
                        }
                        if(r[i + 1][j] > 0 && vis[i + 1][j] != p && check(i + 1, j, r[i + 1][j])){
                            vis[i + 1][j] = p;
                            ans++;
                        }
                    }

                }
            }
            else{
                for(int i = x1; i < x2; i++){
                    up = (int)ceil(getY(i));
                    down = (int)floor(getY(i + 1));
                    if(i == x1) up = y1;
                    if(i == x2 - 1) down = y2;
                    for(int j = down; j <= up; j++){
                        if(r[i][j] > 0 && vis[i][j] != p && check(i, j, r[i][j])){
                            vis[i][j] = p;
                            ans++;
                        }
                        if(r[i + 1][j] > 0 && vis[i + 1][j] != p && check(i + 1, j, r[i + 1][j])){
                            vis[i + 1][j] = p;
                            ans++;
                        }
                    }

                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/KirinSB/p/10829107.html

时间: 2024-10-14 05:32:59

Gym 101480I Ice Igloos(思维乱搞)题解的相关文章

Codeforces Gym 100203G Good elements 暴力乱搞

原题链接:http://codeforces.com/gym/100203/attachments/download/1702/statements.pdf 题解 考虑暴力的复杂度是O(n^3),所以我们需要记录所有的ai+aj,如果当前考虑到了ak,那么就去前面寻找ai,使得ak-ai是我们记录过的和.整个算法的复杂度O(n^2). 代码 #include<iostream> #include<cstring> #include<cstdio> #include<

CodeForces - 1228D (暴力+思维+乱搞)

题意 https://vjudge.net/problem/CodeForces-1228D 有一个n个顶点m条边的无向图,在一对顶点中最多有一条边. 设v1,v2是两个不相交的非空子集,当满足以下条件时f(v1,v2)为真 v1中的点之间不存在边 v2中的点之间不存在边 对于在v1v2中的每一对顶点,x在v1中,y在v2中,xy之间有边 所有点集不为空,且不相交,是否有v1,v2,v3使得f(v1,v2).f(v2,v3).f(v3,v1)均为真 如果有输出每个点所在的点集(1,2,3),否则

hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10

题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include &

【乱搞】【HNOI 2008】【bzoj 1011】遥远的行星

1011: [HNOI2008]遥远的行星 Time Limit: 10 Sec Memory Limit: 162 MBSec Special Judge Submit: 2640 Solved: 954 Description 直线上N颗行星,X=i处有行星i,行星J受到行星I的作用力,当且仅当i<=AJ.此时J受到作用力的大小为 Fi->j=Mi*Mj/(j-i) 其中A为很小的常量,故直观上说每颗行星都只受到距离遥远的行星的作用.请计算每颗行星的受力,只要结果的相对误差不超过5%即可.

[bzoj1356]Rectangle[Baltic2009][几何常识乱搞]

虽然说是几何常识乱搞,但是想不到啊.. 题意:n个点取4个组成矩形,使面积最大,求面积. n<=1500 题解: 1.对角线相等且相互交于中点的四边形是矩形. 2.矩形四点共圆. 所以$n^2$枚举边,把线段中点和长度打包pair 如果两条线的pair相等则可以构成一个圆,把相等的线段平方级枚举即可. 考虑一个圆上的整点不多,常数小,所以没有T..注意精度问题. [学习]http://blog.csdn.net/wzq_qwq/article/details/49005387 感觉自己代码自带大

【bzoj4917】Hash Killer IV 乱搞

题目描述 已知函数: unsigned int Hash(unsigned int v) { unsigned int t = v; t = t + (t << 10); t = t ^ (t >> 6); t = t + (t << 3); t = t ^ (t >> 11); t = t + (t << 16); return t; } 的返回值为t,求传入的参数v. 输入 第一行包含一个正整数Q(1<=Q<=100000),表示

Ural 1780 Gray Code 乱搞暴力

原题链接:http://acm.timus.ru/problem.aspx?space=1&num=1780 1780. Gray Code Time limit: 0.5 secondMemory limit: 64 MB Denis, Vanya and Fedya gathered at their first team training. Fedya told them that he knew the algorithm for constructing aGray code. Cre

【bzoj5108】[CodePlus2017]可做题 拆位+乱搞

题目描述 给出一个长度为 $m$ 的序列 $a$ ,编号为 $a_1\sim a_m$,其中 $n$ 个位置的数已经确定,剩下的位置的数可以任意指定.现在令 $b$ 表示 $a$ 的前缀异或和,求 $\sum\limits_{i=1}^mb_i$ 的最小值. 输入 输入第一行两个非负整数n,m,分别表示原始序列a的长度及剩余元素的个数. 之后m行,每行2个数i,ai,表示一个剩余元素的位置和数值. 1<=N<=10^9,0<=M<=Min(n,10^5),0<=ai<=

[USACO08OCT]牧场散步Pasture Walking (LCA) (乱搞)

题面传送门我太懒了所以吃掉题面 题解 可以发现如果两点不在一条链上的话,那么他们的最短路径一定会经过LCA. 所以可以维护一下每个点到树根的距离,然后大力前缀和乱搞就好了. #include <bits/stdc++.h> const int max_n=1e4+5; int N,M,cnt; int depth[max_n],father[15][max_n],lg2[max_n],first_edge[max_n],dis[max_n]; struct edge { int to,w,ne