Kickstart Round D 2018 B题 Paragliding

2024-01-28 12:48

本文主要是介绍Kickstart Round D 2018 B题 Paragliding,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目大意:有N个塔,水平坐标为 p[i], 高度为 h[i], 每个塔的水平坐标各不相同。 有K个气球,每个气球可看做一个点,坐标为x[i], y[i]。一个人可以爬到每个塔的任意高度位置,然后在该位置可以向左右45度滑行,滑行的轨迹是直线。如果在途中遇到气球,则可获得该气球,如果气球和塔相重叠,也认为可获得气球,要求一共可以获得多少个气球。

解题关键点:

1. 如果从一个塔( p[j], h[j]  )向下滑行可以获得某个气球(x[i], y[i]), 则满足 abs(x[i] - p[j] ) + y[i] <= h[j]

2. 如果一个塔 i 和另外一个塔 j 满足 abs(p[i] - p[j]) + h[i] <= h[j], 则第i个塔是多余的,因为任意从第i个塔滑行获得的气球,都可以通过从第j个塔滑行获得。

解题方法:

1. 小数据: 将每个气球和所有的塔进行关键点1条件比较,如果满足,则该气球可获得。

2. 大数据: 对于每个气球,如果我们能找到能它最近的塔,只判断是否能从离它最近的塔上获得就好了。但是存在这样一个问题,如果从离它最近的塔上不能获得,也许存在离它较远位置的塔,从这些塔上获得气球。这样的话,还得依次遍历所有的塔。为了达到最初的想法,考虑关键点2, 如果我们把所有多余的塔去掉,那么就可以只判断是否能从离它最近的塔上获得就可以了。为什么? 假设某个气球坐标为(x, y) , 离它最近的右边的塔为(p1, h1),从该塔不能获得气球,则满足 p1 - x + y > h1, 该式子等于 -p1 + x - y + h1 < 0, 又假设存在离该气球更远的塔(p2, h2 )  p2 >p1, 从该塔上可以获得气球,则满足 p2 - x + y <= h2, 将这个式子和前面的式子相加得到  p2 - p1 + h1 <= h2,正好关键点2中的条件,也就是说离它最近的那个塔是多余的。 所以,我们把所有多余的塔去掉之后,就可以找到离某个气球最近的塔,找的过程可以将所有的塔从小到大排好序,再使用二分搜索进行查找。

代码:

#include <iostream>
#include <iostream>
#include <string.h>
#include <iomanip>
#include <algorithm>
#include <stdio.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;const int maxn = 100010;
ll p[maxn], h[maxn], x[maxn], y[maxn];
ll relevantT[maxn];
ll towerSorted[maxn];//排好序的塔
map<ll, int> valueAndID; //塔的位置和索引
ll A[5], B[5], C[5], M[5];
int T, N, K;int getRelation(int i, int j)//第i个塔, 第j个塔 i > j
{if(h[j] >= p[i] - p[j] + h[i]) //第i个塔是多余的return 1;if(h[i] >= p[i] - p[j] + h[j]) //第j个塔是多余的return 2;return 3;
}bool ok(int i, int j)//第i个气球,第j个塔
{if(abs(x[i] - p[j]) + y[i] <= h[j])return true;return false;
}int getRelevantTowers()
{for(int i = 1; i <= N; i++){towerSorted[i] = p[i];valueAndID[p[i]] = i;}sort(towerSorted + 1, towerSorted + 1 + N);stack<ll> st;for(int i = 1; i <= N; i++){if(st.empty()){st.push(towerSorted[i]);continue;}int relation = getRelation(valueAndID[towerSorted[i]], valueAndID[st.top()]);if(relation == 1)//多余的continue;if(relation == 2)//栈顶的塔是多余的{st.pop();while(!st.empty() && getRelation(valueAndID[towerSorted[i]], valueAndID[st.top()]) == 2){st.pop();}}st.push(towerSorted[i]);}int len = st.size();int tp = len;while(!st.empty()){relevantT[tp--] = st.top();st.pop();}return len;
}int main()
{freopen("B-large-practice.in", "r", stdin);freopen("out2.txt", "w", stdout);cin >> T;for(int cas = 1; cas <= T; cas++){valueAndID.clear();cin >> N >> K;cin >> p[1] >> p[2] >> A[1] >> B[1] >> C[1] >> M[1];for(int i = 3; i <= N; i++)p[i] = (A[1] * p[i - 1] + B[1] * p[i - 2] + C[1]) % M[1] + 1;cin >> h[1] >> h[2] >> A[2] >> B[2] >> C[2] >> M[2];for(int i = 3; i <= N; i++)h[i] = (A[2] * h[i - 1] + B[2] * h[i - 2] + C[2]) % M[2] + 1;cin >> x[1] >> x[2] >> A[3] >> B[3] >> C[3] >> M[3];for(int i = 3; i <= K; i++)x[i] = (A[3] * x[i - 1] + B[3] * x[i - 2] + C[3]) % M[3] + 1;cin >> y[1] >> y[2] >> A[4] >> B[4] >> C[4] >> M[4];for(int i = 3; i <= K; i++)y[i] = (A[4] * y[i - 1] + B[4] * y[i - 2] + C[4]) % M[4] + 1;int len = getRelevantTowers();int ans = 0;for(int i = 1; i <= K; i++){int L = lower_bound(relevantT + 1, relevantT + 1 + len, x[i]) - relevantT;//和塔重叠if(x[i] == relevantT[L]){if(ok(i, valueAndID[relevantT[L]]))ans++;continue;}//该气球在最左边if(L == 1){if(ok(i, valueAndID[relevantT[L]]))ans++;continue;}//该气球在最右边if(L > len){if(ok(i, valueAndID[relevantT[len]]))ans++;continue;}//该气球处在两个塔之间int LL = L - 1;int RR = L;if(ok(i, valueAndID[relevantT[LL]])){ans++;continue;}if(ok(i, valueAndID[relevantT[RR]]))ans++;}cout << "Case #" << cas <<": " << ans <<endl;}return 0;
}

 

这篇关于Kickstart Round D 2018 B题 Paragliding的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/653676

相关文章

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

2018秋招C/C++面试题总结

博主从8月中旬开始大大小小面试了十几家公司,至今也许是告一段落吧,希望后面会有好结果,因此总结记录一些C/C++方向常见的问题。和大家一起学习! 参考了互联网的各种资源,自己尝试归类整理,谢谢~ 一、C和C++的区别是什么? C是面向过程的语言,C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛。 C中函数不能进行重载,C++函数可以重载 C++在C的基础上增添类,C是一个结构

Codeforces Round 971 (Div. 4) (A~G1)

A、B题太简单,不做解释 C 对于 x y 两个方向,每一个方向至少需要 x / k 向上取整的步数,取最大值。 由于 x 方向先移动,假如 x 方向需要的步数多于 y 方向的步数,那么最后 y 方向的那一步就不需要了,答案减 1 代码 #include <iostream>#include <algorithm>#include <vector>#include <string>

大厂算法例题解之网易2018秋招笔试真题 (未完)

1、字符串碎片 【题目描述】一个由小写字母组成的字符串可以看成一些同一字母的最大碎片组成的。例如,“aaabbaaac” 是由下面碎片组成的:‘aaa’,‘bb’,‘c’。牛牛现在给定一个字符串,请你帮助计算这个字符串的所有碎片的 平均长度是多少。 输入描述: 输入包括一个字符串 s,字符串 s 的长度 length(1 ≤ length ≤ 50),s 只含小写字母(‘a’-‘z’) 输出描述

MemSQL Start[c]UP 2.0 - Round 1A(构造)

题目链接:http://codeforces.com/problemset/problem/452/A 解题思路: 打个表暴力查找匹配。 完整代码: #include <algorithm>#include <iostream>#include <cstring>#include <complex>#include <cstdio>#include <strin

Codeforces Round #281 (Div. 2)A(构造+暴力模拟)

题目链接:http://codeforces.com/problemset/problem/493/A 解题思路: 暴力的判断,分三种情况去判断即可。注意如果之前已经被罚下场后,那么在后面的罚下情况不应该算在输出结果内。 完整代码: #include <algorithm>#include <iostream>#include <cstring>#include <co