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; }