计蒜客2019CSP比赛第一场
巧妙避开这场比赛……
T1炮击
题目描述
\(rize\) 是一个可爱的女孩子。
一天,\(rize\) 进行了炮击的练习。炮击用的靶子为一个圆,其中有 \(n-1\) 个与靶子同心的圆,将靶子划分成了 \(n\) 个区域。这些区域里到外从 \(1\) 到 \(n\) 编号,第 \(i\) 个区域的外径为 \(R_i\) 。每个区域有一个分数,第 \(i\) 个区域的分数为 \(s_i\) 。\(rize\) 发射了 \(m\) 枚炮弹。在靶平面上的以靶心为原点的直角坐标系下,第 \(i\) 枚炮弹击中的区域为一个半径为 \(r_i\)的圆,其圆心的坐标为 \((x_i, y_i)\) 。若一枚炮弹击中的区域与靶子中的某个区域存在交集,则发射这枚炮弹会得到这个区域的分数。这里的区域不包含边界。
\(rize\) 想知道发射每一枚炮弹的得分。
输入格式
第一行两个数 \(n, m\) ;
之后 \(n\) 行,每行两个整数 \(R_i, s_i\);
之后 \(m\) 行,每行三个整数 \(x_i, y_i, r_i\) 。
输出格式
\(m\)行,每行一个数表示答案。
数据范围
有 \(30\%\) 的数据 \(n, m \le 1000\) ;
另有 \(20\%\) 的数据 \(r_i = 1\);
另有 \(20\%\) 的数据 \(s_i = 1\);
对于 \(100\%\) 的数据,\(1 \le n, m \le 2 \times 10^5\),\(1 \le s_i \le 10^4\),\(-10^7 \le x_i, y_i \le 10^7\) ,\(1 \le r_i \le 10^7\) ,\(1 \le R_1 < R_2 < \cdots < R_n \le 10^7\)
“这是一道大水题”
我当时这么说的,但是直到最后我这个蒟蒻还是没写出来……
二分查找\(+\)前缀和
我们可以发现,对于每发炮弹,我们并不需要计算圆的大小,真正需要算的只有它的圆心和靶心的连线的距离分别加减它的半径:\(\sqrt{x^2 + y^2} + r\)是最远点,最近点需要特判,当\(\sqrt{x^2 + y^2} < r\)时最近点是圆心,否则是\(\sqrt{x^2 + y^2} - r\),然后考虑优化,就可以用前缀和,在考虑如何查找前缀和,就可以想到\(logn\)的二分查找……还挺绕
代码:
#include<bits/stdc++.h> using namespace std; #define rint register int #define lb lower_bound #define ub upper_bound int n, m; int f[300010], c[300010]; inline int read( void ){ int re = 0, f = 1;char ch = getchar(); while( ch > '9' || ch < '0' ){ if( ch == '-' ) f = -1; ch = getchar(); } while( ch >= '0' && ch <= '9' ){ re = re * 10 + ch - '0'; ch = getchar(); } return re * f; } int main( void ){ n = read(); m = read(); for( rint i = 1; i <= n; i++ ){ c[i] = read(); f[i] = read() + f[i - 1]; } for( rint i = 1; i <= m; i++ ){ double x, y; int r; x = read(); y = read(); r = read(); double dis = sqrt( x * x + y * y ); printf("%d\n",f[lb(c,c+n,(int)ceil(dis)+r)-c]-(dis<=r?0:f[ub(c+1,c+n+1, (int)dis-r)-c-1])); } return 0; }
T2出行
还行,想出了正解,没想到处理方法
题目描述
\(syaro\) 是一个可爱的女孩子。
\(syaro\) 所在的城市有 \(n\)个街区,街区之间共有 \(m\) 条双向通行的道路,且任意两个街区可以通过这些道路互相到达。
一天,\(syaro\) 要带着无数只兔子从 \(1\) 号街区走到 \(n\) 号街区。由于 \(syaro\) 无法管理太多的兔子,于是她决定,如果她经过的道路中存在长度为 \(w\) 的道路,那么她出发时只会带不大于 \(w\) 只兔子。为了节省时间,她只会在总长度最短的若干条路径中选择一条走。
另外,有 \(k\) 个街区由于开了很多咖啡店,整个街区都弥漫着咖啡的气味。由于 \(syaro\) 闻到咖啡的气味就会迷失方向,因此她只会从不经过任何一个这样的街区的最短路径中选择一条走。如果所有最短路径都会经过这样的街区,她就会放弃出行。
\(syaro\) 告诉了 \(cocoa\) 自己的出行计划。 \(cocoa\) 作为一个擅长算术的女孩子,想知道 \(syaro\) 最多能带多少只兔子。当然,放弃出行意味着最多能带 \(0\) 只兔子。
输入格式
第一行三个数 \(n, m, k\) ;
第二行 \(k\)个数,表示开了很多咖啡店的街区编号;
之后$ m$ 行,每行三个数 \(u, v, w\),表示有一条从 \(u\) 到 \(v\) 的长度为 \(w\) 的道路。
输出格式
输出一行一个数表示答案。
数据范围
对于 \(10\%\) 的数据 \(n, m \le 50\), \(m-n \le 10\);
对于 \(30\%\) 的数据 \(n, m \le 10^3\)
;
对于 \(60\%\)的数据 \(n, m \le 10^5\)
;
另有 \(20\%\)的数据 \(k = 0\) ;
对于 \(100\%\) 的数据 \(1 \le n, m \le 10^6\)
,\(0 \le k \le n0≤k≤n,0 \le w \cdot n \le 10^9\)
。不保证没有重边,保证没有自环。
很明显这题是要把有咖啡店的点标记然后不向它们连边
然后在新图上找一下最短路里的最大边
当时不知道怎么想的,跑了个二分答案,二分边的长度,其实正确性有所保证,但是每次二分要跑一个\(O(nlogn)\)的\(dij\),\(1e6\)跑一个\(O(nlogn)\)没有问题的,于是我理所应当的忽略了前面那个二分答案的\(O(logn)\),单单一个\(O(logn)\)不大,但是\(O(logn^2)\)就得考虑一下了,再加上计蒜客的评测姬跑得不快,导致我几乎没拿分
标答应该是\(dp\)
未完……