2019牛客多校(第十场)F Popping Balloons —— 线段树+枚举

https://ac.nowcoder.com/acm/contest/890/F

题意:二维平面中有n个气球,你可以横着社三法子弹,竖着射三发子弹,且横着子弹的关系是y,y+r,y+2*r,竖着是x,x+r,x+2*r。问你怎么射才能射爆最多的气球。

分析:(代码注释)

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
const int M=3e5+5;
int n,m;
vector<int>mp[M];
int tree[M<<2];
void up(int root){
    tree[root]=max(tree[root<<1],tree[root<<1|1]);
}

void update(int pos,int val,int root,int l,int r){
    if(l==r){
        tree[root]+=val;
        return ;
    }
    int midd=(l+r)>>1;
    if(pos<=midd)
        update(pos,val,lson);
    else
        update(pos,val,rson);
    up(root);
}
void change(int pos,int val){
    update(pos,val,1,1,1e5+1);
    if(pos-m>=1)
        update(pos-m,val,1,1,1e5+1);
    if(pos-2*m>=1)
        update(pos-2*m,val,1,1,1e5+1);
}
int main(){
    
    scanf("%d%d",&n,&m);
    int ans=0;
    for(int i=1;i<=n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        x++,y++;
        mp[x].pb(y);
        change(y,1);
    }
    for(int i=1;i<=1e5+1;i++){
        ///三行贡献 
        int hang=mp[i].size()+mp[i+m].size()+mp[i+2*m].size();
        ///求去掉三行后的三列最大贡献 
        for(int j=0;j<mp[i].size();j++){
            change(mp[i][j],-1);
        }
        for(int j=0;j<mp[i+m].size();j++){
            change(mp[i+m][j],-1);
        }
        for(int j=0;j<mp[i+2*m].size();j++){
            change(mp[i+2*m][j],-1);
        }
        ans=max(ans,hang+tree[1]);
        ///加回来为了下一次计算做准备 
        for(int j=0;j<mp[i].size();j++){
            change(mp[i][j],1);
        }
        for(int j=0;j<mp[i+m].size();j++){
            change(mp[i+m][j],1);
        }
        for(int j=0;j<mp[i+2*m].size();j++){
            change(mp[i+2*m][j],1);
        }
    }
    printf("%d",ans);
    return 0; 
}
View Code
原文地址:https://www.cnblogs.com/starve/p/11376979.html