ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)
题意是说有n把枪,有m个靶子,每把枪只有一发子弹(也就是说一把枪最多只能打一个靶子), 告诉你第 i 把枪可以打到第j个靶, 现在等概率的出现一个连续的P把枪,在知道这P把枪之后,你被允许选择一个连续的Q个靶子,使得这P把枪所打到的靶子的数目最多,问打到的靶子数目的期望值是多少。
这题通过简单的转化就可以转换成为另一个模型:
如果第a把枪可以打到第b个靶子,那么将其视为二位平面上的一个点(b, a), 问题转化为一个Q * P的矩形最多可以覆盖多少个点。只是有一点需要注意的就是同一把枪只能打到一个靶子,所以在a相等的情况下最多只能覆盖一个b。
至于如何求矩形覆盖点的个数,我这也是第一次写,所以查阅了有关资料。
方法是将矩形的右界作为参考点,找出参考点在哪一个区间(线段)内矩形都可以覆盖到这个点,这样每一个点就对应y相等的一段线段,原题就转化成为了高度y小于P的区间内某一个位置x上的覆盖次数的最大值,可以用线段树的离线操作(扫描线)来完成。
- #include <map>
- #include <set>
- #include <stack>
- #include <queue>
- #include <cmath>
- #include <ctime>
- #include <vector>
- #include <cstdio>
- #include <cctype>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #define INF 0x3f3f3f3f
- #define inf (-((LL)1<<40))
- #define lson k<<1, L, (L + R)>>1
- #define rson k<<1|1, ((L + R)>>1) + 1, R
- #define mem0(a) memset(a,0,sizeof(a))
- #define mem1(a) memset(a,-1,sizeof(a))
- #define mem(a, b) memset(a, b, sizeof(a))
- #define FIN freopen("in.txt", "r", stdin)
- #define FOUT freopen("out.txt", "w", stdout)
- #define rep(i, a, b) for(int i = a; i <= b; i ++)
- template<class T> T CMP_MIN(T a, T b) { return a < b; }
- template<class T> T CMP_MAX(T a, T b) { return a > b; }
- template<class T> T MAX(T a, T b) { return a > b ? a : b; }
- template<class T> T MIN(T a, T b) { return a < b ? a : b; }
- template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
- template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; }
- //typedef __int64 LL;
- typedef long long LL;
- const int MAXN = ;
- const int MAXM = ;
- const double eps = 1e-;
- //LL MOD = 987654321;
- #define OK(i) (i > 0 && p[i - 1].y == p[i].y && p[i].x <= p[i - 1].x + Q - 1)
- int T, N, M, P, Q, K;
- struct Point {
- int x, y;
- bool operator < (const Point &A) const {
- return y == A.y ? x < A.x : y < A.y;
- }
- }p[MAXM];
- struct SegTree {
- LL ma[MAXN<<], add[MAXN<<];
- void build(int k, int L, int R) {
- ma[k] = add[k] = ;
- if(L == R) return ;
- build(lson); build(rson);
- }
- void pushDown(int k) {
- ma[k<<] += add[k]; add[k<<] += add[k];
- ma[k<<|] += add[k]; add[k<<|] += add[k];
- add[k] = ;
- }
- void update(int k, int L, int R, int l, int r, int val) {
- if(R < l || L > r) return ;
- if(l <= L && R <= r) { ma[k] += val; add[k] += val; return ; }
- pushDown(k);
- update(lson, l, r, val);
- update(rson, l, r, val);
- ma[k] = max(ma[k<<], ma[k<<|]);
- }
- LL query(int k, int L, int R, int l, int r) {
- if(R < l || L > r) return ;
- if(l <= L && R <= r) return ma[k];
- pushDown(k);
- return max(query(lson, l, r), query(rson, l, r));
- }
- }segTree;
- int main()
- {
- //FIN;
- while(~scanf("%d", &T)) while(T--)
- {
- scanf("%d %d %d %d %d", &N, &M, &P, &Q, &K);
- rep (i, , K - ) scanf("%d %d", &p[i].y, &p[i].x);
- sort(p, p + K);
- segTree.build(, , M);
- LL ans = , fr = , re = ;
- rep (i, P, N) {
- while(fr < K && p[fr].y <= i) {
- int st = OK(fr) ? p[fr-].x + Q : p[fr].x;
- int ed = min(p[fr].x + Q - , M);
- segTree.update(, , M, st, ed, );
- fr ++;
- }
- while(i - p[re].y >= P) {
- int st = OK(re) ? p[re-].x + Q : p[re].x;
- int ed = min(p[re].x + Q - , M);
- segTree.update(, , M, st, ed, -);
- re ++;
- }
- ans += segTree.query(, , M, , M);
- }
- printf("%.2lf\n", (double)ans / (N - P + ));
- }
- return ;
- }
ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)的更多相关文章
- hdu 1828 Picture(线段树扫描线矩形周长并)
线段树扫描线矩形周长并 #include <iostream> #include <cstdio> #include <algorithm> #include &l ...
- HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)
版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...
- hdu1828 Picture(线段树+扫描线+矩形周长)
看这篇博客前可以看一下扫描线求面积:线段树扫描线(一.Atlantis HDU - 1542(覆盖面积) 二.覆盖的面积 HDU - 1255(重叠两次的面积)) 解法一·:两次扫描线 如图我们可以 ...
- poj 3277 City Horizon (线段树 扫描线 矩形面积并)
题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不 ...
- ZOJ-3597-Hit the Target!(线段树+扫描线)
题解引自:http://www.cnblogs.com/wuyiqi/archive/2012/04/28/2474614.html 这题和着题解一块看,看了半天才看懂的....菜菜.... 题意:有 ...
- 【学习笔记】线段树—扫描线补充 (IC_QQQ)
[学习笔记]线段树-扫描线补充 (IC_QQQ) (感谢 \(IC\)_\(QQQ\) 大佬授以本内容的著作权.此人超然于世外,仅有 \(Luogu\) 账号 尚可膜拜) [学习笔记]线段树详解(全) ...
- 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))
扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...
- hdu1542 Atlantis (线段树+扫描线+离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
随机推荐
- linux修改文件夹及其子文件夹的权限
加入-R 参数,就可以将读写权限传递给子文件夹例如chmod -R 777 /home/mypackage那么mypackage 文件夹和它下面的所有子文件夹的属性都变成了777.777是读.写.执行 ...
- kdtree备份
库在这里 这个很好用. 例子: /*! gcc -Wall -g -o test test.c libkdtree.a */ #include <stdio.h> #include < ...
- C++ 编写Windows service
最近实现一个windows server端守护进程启动服务功能(c++实现),遇到了一些问题,记录一下 1. 启动Service实现代码: int _tmain(int argc, TCHAR* ar ...
- unity, audio falloff
要达到声音随距离衰减的效果,需要使用3D音效,即把Spatial Blend设为1,然后再调节Min Distance和Max Distance(蓝色线框球体),并选择合适的Volume Rollof ...
- MySQL与Oracle 差异比较之二基本语法
基本语法 编号 类别 ORACLE MYSQL 注释 1 变量的声明方式不同 li_index NUMBER := 0 DECLARE li_index INTEGER DEFAULT 0 1. my ...
- SpatiaLite 各版本数据库差异
SpatiaLite 生成的数据库,3.0版本与4.0版本的表geometry_columns结构发生变化. 这是3.0版本的结构: 这是4.0版本的结构: 主要差别是type和coord_dimen ...
- zz github配置
First : 安装:ubuntu 下,终端输入命令: sudo apt-get install git-core git-gui git-doc Next : 设置SSH Key 检查是否已经有SS ...
- poj 2409(polya定理模板)
题意:给你n种颜色和m个小球,问你有多少种不同的方案! 分析:作为模板.. 代码实现: #include <iostream> #include <cstdio> #inclu ...
- N元数组的子数组之和的最大值
题目:有N个整数的元素的一维数组,求子数组中元素之和中最大的一组(思想:动态规划) 分析: 设该数组为array[N], 那么对于array[i]该不该在元素之和最大的那个子数组中呢?首先,不如假设a ...
- propertyGrid控件 z
1.如果属性是enum类型,那么自然就是下拉的. 2.如果是你自定义的下拉数据,那么需要用到转换属性标签TypeConverter 参见: http://blog.csdn.net/luyifeini ...