これは典型かな…。
https://yukicoder.me/problems/no/1490
問題
H*Wのグリッドがあり、そこにN体のスライムがいる。
各スライムはグリッド上である矩形領域を占める。また、その体力が与えられる。
ここに、M個の爆弾を配置する。
各爆弾は、やはりグリッド上である矩形領域を占め、1マスあたりに与えるダメージが指定されている。
各スライムは、占める領域における爆弾のダメージの総和が、体力以上である場合に消滅する。
生き残るスライムの数を求めよ。
解法
累積和を何度も使う。
まず、爆弾に関し、累積和を使い、各マスに与えるダメージの総和を計算する。
次の、そのダメージを累積和を取ることで、矩形区間内の総ダメージをO(1)で計算できるようにする。
最後に各スライムの占める領域の総ダメージを求めよう。
int H,W,N,M; int T[202020],U[202020],L[202020],R[202020],A[202020]; ll S[2020][2020]; void solve() { int i,j,k,l,r,x,y; string s; cin>>H>>W>>N>>M; FOR(i,N) { cin>>T[i]>>U[i]>>L[i]>>R[i]>>A[i]; } FOR(i,M) { int b; cin>>y>>x>>b>>r; S[max(1,y-b)][max(1,x-b)]+=r; S[min(2010,y+b+1)][max(1,x-b)]-=r; S[max(1,y-b)][min(2010,x+b+1)]-=r; S[min(2010,y+b+1)][min(2010,x+b+1)]+=r; } FOR(y,H+2) FOR(x,W+2) { if(y) S[y][x]+=S[y-1][x]; if(x) S[y][x]+=S[y][x-1]; if(y&&x) S[y][x]-=S[y-1][x-1]; } FOR(y,H+2) FOR(x,W+2) { if(y) S[y][x]+=S[y-1][x]; if(x) S[y][x]+=S[y][x-1]; if(y&&x) S[y][x]-=S[y-1][x-1]; } int ret=0; FOR(i,N) { ll d=S[U[i]][R[i]]-S[T[i]-1][R[i]]-S[U[i]][L[i]-1]+S[T[i]-1][L[i]-1]; if(d<A[i]) ret++; } cout<<ret<<endl; }
まとめ
2次元累積和はいい加減ライブラリにすべきか…。