ZOJ-3597-Hit the Target!(线段树+扫描线)

题解引自:http://www.cnblogs.com/wuyiqi/archive/2012/04/28/2474614.html

这题和着题解一块看,看了半天才看懂的....菜菜....

题意:有一排的枪编号依次为1~n 有一排靶子编号依次为1~m

告诉你哪些枪能打中哪些靶子,然后如果每次只能选连续的P把枪,连续的Q个靶子,每次能打中的靶子的最大值为多少

答案是把每次打中的最大值相加再除以总的次数

即选择 1~P 的枪能打中的最多的靶子的数量 + 2~p+1 的枪能打中的最多的靶子的数量 +。。。n-p+1~n的枪能打中的最多的靶子的数量 /(n-p+1)

注意,每把枪最多只能打一个靶子

解法:将题目中的关系转换为坐标 以枪为纵坐标 a 能打中 b ,在坐标系中为(b,a),然后连续的P把枪和连续的Q个靶子则可以表示为

用一个P x Q的矩形去覆盖,最多能覆盖的总的点数,就是poj 2482 了,但要注意一点,如果两根同一高度的水平线的距离小于Q,则重叠的部分职能算一次,因为每把枪只能打一个靶子

// File Name: 3597.cpp
// Author: Zlbing
// Created Time: 2013/7/21 14:25:06

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int MAXN=5e4+100;
struct point{
    int x,y;
    bool operator <(const point& rsh)const{
        if(y==rsh.y)return x<rsh.x;
        else return y<rsh.y;
    }
}G[100050];

int sum[MAXN<<2];
int col[MAXN<<2];

void pushup(int rt)
{
    sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}
void pushdown(int rt)
{
    if(col[rt])
    {
        sum[rt<<1]+=col[rt];
        sum[rt<<1|1]+=col[rt];
        col[rt<<1]+=col[rt];
        col[rt<<1|1]+=col[rt];
        col[rt]=0;
    }
}
void update(int L,int R,int flag,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        col[rt]+=flag;
        sum[rt]+=flag;
        return;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,flag,lson);
    if(R>m)update(L,R,flag,rson);
    pushup(rt);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,p,q,K;
        scanf("%d%d%d%d",&n,&m,&p,&q);
        scanf("%d",&K);
        for(int i=0;i<K;i++)
        {
            scanf("%d%d",&G[i].y,&G[i].x);
        }
        sort(G,G+K);
        int ans=0;
        int j=0,k=0;
        CL(sum,0);
        CL(col,0);
        for(int i=1;i+p-1<=n;i++)
        {
            
            for(;G[j].y-i<p&&j<K;j++)
            {
                if(j+1<K&&G[j].y==G[j+1].y&&G[j+1].x-G[j].x<q)
                    update(G[j].x,G[j+1].x-1,1,1,m,1);
                else
                    update(G[j].x,min(m,G[j].x+q-1),1,1,m,1);
            }
            ans+=sum[1];
            for(;k<j&&G[k].y==i;k++)
            {
                if(k+1<j&&G[k].y==G[k+1].y&&G[k+1].x-G[k].x<q)
                    update(G[k].x,G[k+1].x-1,-1,1,m,1);
                else 
                    update(G[k].x,min(m,G[k].x+q-1),-1,1,m,1);
            }
        }
        printf("%.2lf
",(double)ans/(n-p+1));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/arbitrary/p/3203785.html