码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-05-10 22:16:57      阅读:310      评论:0      收藏:0      [点我收藏+]

标签:

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 }

 

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

标签:

原文地址:http://www.cnblogs.com/gj-Acit/p/4493091.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!