Hit the Target! ZOJ - 3597

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3597

对于每枝枪的每颗子弹 设射击位置为pos 将[pos,pos+q-1]均加1 这时线段树上第i个叶节点维护的就是[i-q+1,i]的区间和 对于每个连续的p长区间 取最大值即可 还有注意 因为每枝枪只能打一发 所以对于同枝枪的不同子弹所更新的区间绝不能重叠 这里排下序去个重即可

扫描线的题除了求周长面积外 其他题型都没必要刻意考虑扫描不扫描

 

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
const int maxn=5e4+10;
const int maxm=1e5+10;

struct node
{
    int l,r;
};

vector <int> pre[maxn];
node seg[maxm];
int maxx[4*maxn],laz[4*maxn];
int n,m,p,q,k;

void pushup(int cur)
{
    maxx[cur]=max(maxx[2*cur],maxx[2*cur+1]);
}

void pushdown(int cur)
{
    if(laz[cur]!=0){
        maxx[2*cur]+=laz[cur];
        laz[2*cur]+=laz[cur];
        maxx[2*cur+1]+=laz[cur];
        laz[2*cur+1]+=laz[cur];
        laz[cur]=0;
    }
}

void update(int pl,int pr,int val,int l,int r,int cur)
{
    int m;
    if(pl<=l&&r<=pr){
        maxx[cur]+=val;
        laz[cur]+=val;
        return;
    }
    pushdown(cur);
    m=(l+r)/2;
    if(pl<=m) update(pl,pr,val,l,m,2*cur);
    if(pr>m) update(pl,pr,val,m+1,r,2*cur+1);
    pushup(cur);
}

bool cmp(node n1,node n2)
{
    return n1.l<n2.l;
}

void solve(int id,int val)
{
    int i,gou;
    for(i=0;i<pre[id].size();i++){
        seg[i+1].l=pre[id][i],seg[i+1].r=min(m,pre[id][i]+q-1);
    }
    sort(seg+1,seg+pre[id].size()+1,cmp);
    gou=0;
    for(i=1;i<=pre[id].size();i++){
        if(seg[i].r>=gou+1){
            update(max(gou+1,seg[i].l),seg[i].r,val,1,m,1);
            gou=seg[i].r;
        }
    }
}

int main()
{
    double ans;
    int t,i,j,gun,tar;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d",&n,&m,&p,&q,&k);
        for(i=1;i<=n;i++){
            pre[i].clear();
        }
        while(k--){
            scanf("%d%d",&gun,&tar);
            pre[gun].pb(tar);
        }
        for(i=1;i<=4*m;i++){
            maxx[i]=0,laz[i]=0;
        }
        for(i=1;i<=p-1;i++){
            solve(i,1);
        }
        ans=0.0;
        for(i=p;i<=n;i++){
            solve(i,1);
            ans+=(double)(maxx[1]);
            solve(i-p+1,-1);
        }
        printf("%.2f\n",ans/(double)(n-p+1));
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值