ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)

ZOJ 3597

题意是说有n把枪,有m个靶子,每把枪只有一发子弹(也就是说一把枪最多只能打一个靶子), 告诉你第 i 把枪可以打到第j个靶, 现在等概率的出现一个连续的P把枪,在知道这P把枪之后,你被允许选择一个连续的Q个靶子,使得这P把枪所打到的靶子的数目最多,问打到的靶子数目的期望值是多少。

这题通过简单的转化就可以转换成为另一个模型:

如果第a把枪可以打到第b个靶子,那么将其视为二位平面上的一个点(b, a), 问题转化为一个Q * P的矩形最多可以覆盖多少个点。只是有一点需要注意的就是同一把枪只能打到一个靶子,所以在a相等的情况下最多只能覆盖一个b。

至于如何求矩形覆盖点的个数,我这也是第一次写,所以查阅了有关资料。

方法是将矩形的右界作为参考点,找出参考点在哪一个区间(线段)内矩形都可以覆盖到这个点,这样每一个点就对应y相等的一段线段,原题就转化成为了高度y小于P的区间内某一个位置x上的覆盖次数的最大值,可以用线段树的离线操作(扫描线)来完成。

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf (-((LL)1<<40))
 17 #define lson k<<1, L, (L + R)>>1
 18 #define rson k<<1|1,  ((L + R)>>1) + 1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FIN freopen("in.txt", "r", stdin)
 23 #define FOUT freopen("out.txt", "w", stdout)
 24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
 25
 26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
 27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
 28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 32
 33 //typedef __int64 LL;
 34 typedef long long LL;
 35 const int MAXN = 51000;
 36 const int MAXM = 110000;
 37 const double eps = 1e-4;
 38 //LL MOD = 987654321;
 39
 40 #define OK(i) (i > 0 && p[i - 1].y == p[i].y && p[i].x <= p[i - 1].x + Q - 1)
 41
 42 int T, N, M, P, Q, K;
 43 struct Point {
 44     int x, y;
 45     bool operator < (const Point &A) const {
 46         return y == A.y ? x < A.x : y < A.y;
 47     }
 48 }p[MAXM];
 49
 50 struct SegTree {
 51     LL ma[MAXN<<2], add[MAXN<<2];
 52
 53     void build(int k, int L, int R) {
 54         ma[k] = add[k] = 0;
 55         if(L == R)  return ;
 56         build(lson); build(rson);
 57     }
 58
 59     void pushDown(int k) {
 60         ma[k<<1] += add[k];   add[k<<1] += add[k];
 61         ma[k<<1|1] += add[k]; add[k<<1|1] += add[k];
 62         add[k] = 0;
 63     }
 64
 65     void update(int k, int L, int R, int l, int r, int val) {
 66         if(R < l || L > r) return ;
 67         if(l <= L && R <= r) { ma[k] += val; add[k] += val; return ; }
 68         pushDown(k);
 69         update(lson, l, r, val);
 70         update(rson, l, r, val);
 71         ma[k] = max(ma[k<<1], ma[k<<1|1]);
 72     }
 73
 74     LL query(int k, int L, int R, int l, int r) {
 75         if(R < l || L > r) return 0;
 76         if(l <= L && R <= r) return ma[k];
 77         pushDown(k);
 78         return max(query(lson, l, r), query(rson, l, r));
 79     }
 80
 81 }segTree;
 82
 83 int main()
 84 {
 85     //FIN;
 86     while(~scanf("%d", &T)) while(T--)
 87     {
 88         scanf("%d %d %d %d %d", &N, &M, &P, &Q, &K);
 89         rep (i, 0, K - 1) scanf("%d %d", &p[i].y, &p[i].x);
 90         sort(p, p + K);
 91
 92         segTree.build(1, 1, M);
 93         LL ans = 0, fr = 0, re = 0;
 94         rep (i, P, N) {
 95             while(fr < K && p[fr].y <= i) {
 96                 int st = OK(fr) ? p[fr-1].x + Q : p[fr].x;
 97                 int ed = min(p[fr].x + Q - 1, M);
 98                 segTree.update(1, 1, M, st, ed, 1);
 99                 fr ++;
100             }
101             while(i - p[re].y >= P) {
102                 int st = OK(re) ? p[re-1].x + Q : p[re].x;
103                 int ed = min(p[re].x + Q - 1, M);
104                 segTree.update(1, 1, M, st, ed, -1);
105                 re ++;
106             }
107             ans += segTree.query(1, 1, M, 1, M);
108         }
109         printf("%.2lf\n", (double)ans / (N - P + 1));
110     }
111     return 0;
112 }
时间: 2024-10-05 01:19:37

ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)的相关文章

poj 3277 City Horizon (线段树 扫描线 矩形面积并)

题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不会出错, 所有的区间都能列出来,只是在查找的时候费点事. 给的矩形相当于在同一水平线上的,也就是y1坐标相当于为0,其他的就和 poj 1151 Atlantis 差不多了. 我写的思路是按照矩形面积并的思路写的: 但是还有另一种方法也是挺简单的,就是把给的矩形按照高从小到大排序,然后依次插入线段树

HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

Problem A : Counting Squares From:HDU, 1264 Problem Description Your input is a series of rectangles, one per line. Each rectangle is specified as two points(X,Y) that specify the opposite corners of a rectangle. All coordinates will be integers in t

线段树扫描线 求矩阵的覆盖面积

题意:给出几个矩阵求这些矩阵覆盖的面积: 给出左上角与右下角 Sample Input 20 5 4 12 4 6 2 Sample Output 20 #include<bits/stdc++.h> #define LL long long #define lson l, m, rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn = 5e3 + 10; const int Base

HDU 3265 Posters(线段树扫描线&#183;矩形框面积并)

题意  把一些矩形海报挖去一部分小矩形贴在指定位置  问最后海报覆盖的面积 一个矩形框可以分割成4个独立的小矩形  然后就能用扫描线求面积并了 #include <cstdio> #include <algorithm> using namespace std; const int N = 100005, M = N << 2; typedef long long ll; struct SLine { int x, y1, y2, flag; SLine() {}; S

【BZOJ】1382: [Baltic2001]Mars Maps (线段树+扫描线)

1382: [Baltic2001]Mars Maps Time Limit: 5 Sec  Memory Limit: 64 MB Description 给出N个矩形,N<=10000.其坐标不超过10^9.求其面积并 Input 先给出一个数字N,代表有N个矩形. 接下来N行,每行四个数,代表矩形的坐标. Output 输出面积并 Sample Input 2 10 10 20 20 15 15 25 30 Sample Output 225 本以为是傻逼题,没想到不容易啊- 线段树+扫描

BZOJ 4059 Cerc2012 Non-boring sequences 线段树+扫描线

题目大意:定义一个序列为[不无聊的]当且仅当这个序列的任意一个区间都存在一个数只出现过一次,给定一个序列,要求判断这个序列是否是[不无聊的] 定义lasti表示第i个元素上一次出现的位置(第一次出现则为0),nexti表示第i个元素下一次出现的位置(最后一次出现则为n+1),那么这个元素能成为某个区间仅出现一次的数,当且仅当这个区间的左端点在[lasti+1,i]之间,右端点在[i,nexti?1]之间 我们可以将区间的左右端点放在二维平面上,那么一个元素产生的贡献是一个矩形,我们要确定的是所有

HDU 4419 Colourful Rectangle --离散化+线段树扫描线

题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何维护每种颜色的长度着实让我伤透了脑筋.后来看了一位朋友的题解,才幡然醒悟. 开始想到了用二进制表示颜色,R用001表示,G用010表示,B用100表示.那么就可以用十进制1~7表示7种不同颜色了. 维护 cov[rt][1~3] 表示此区间内3种原色各有多少个, Len[rt][i]表示每种颜色的长

ZOJ 3772 Calculate the Function 线段树+矩阵

Calculate the FunctionTime Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Appoint description:  System Crawler  (2014-04-09) Description You are given a list of numbers A1A2 .. AN and M queries. For the i-th query

ZOJ 3633 Alice&#39;s present(线段树)

As a doll master, Alice owns a wide range of dolls, and each of them has a number tip on it's back, the tip can be treated as a positive integer. (the number can be repeated). One day, Alice hears that her best friend Marisa's birthday is coming , so