题解:CF1651F Tower Defense
题目传送门
题目大意
给出
解题思路
注意到数据范围,发现
我们对塔进行分块,块的大小为
现在考虑怎么预处理出每个块在经过
所以我们可以先对每个块增加
之后如果怪物血量大于等于块的血量,就直接对块进行操作,否则就暴力计算。
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3010101;
ll n,m,tot,a[N],c[N],h[N],r[N],L[N],R[N],vis,t[N],f[N],ans;
void js(ll x,ll y,ll s,ll t){
vis=0;
for(int i=L[x];i<=R[x];i++){
a[i]=min(c[i],a[i]+(s-t)*r[i]);
if(a[i]<=h[y]){
h[y]-=a[i];
a[i]=0;
}
else{
a[i]-=h[y];
h[y]=0,vis=1;
}
}
}
void solve(ll x){
vis=1;
ll ti=0;
for(int i=0;i<=5e5;i++)f[i]=0;
for(int i=L[x];i<=R[x];i++){
f[1]+=r[i];
f[c[i]/r[i]+1]-=r[i];
}
for(int i=1;i<=5e5;i++)f[i]+=f[i-1];
for(int i=L[x];i<=R[x];i++)f[c[i]/r[i]+1]+=c[i]%r[i];
for(int i=1;i<=5e5;i++)f[i]+=f[i-1];
for(int i=1;i<=m;i++){
if(!h[i])continue;
ll now=L[x]+t[i]-1;
if(vis)js(x,i,now,ti);
else{
if(h[i]<f[now-ti])js(x,i,now,ti);
else h[i]-=min(f[now-ti],h[i]);
}
ti=now;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
tot=sqrt(n)+1;
for(int i=1;i<=n;i++)cin>>c[i]>>r[i],a[i]=c[i];
for(int i=1;i<=tot;i++){
L[i]=R[i-1]+1;
R[i]=min(n,i*tot);
}
cin>>m;
for(int i=1;i<=m;i++)cin>>t[i]>>h[i];
for(int i=1;i<=tot;i++)solve(i);
for(int i=1;i<=m;i++)ans+=h[i];
cout<<ans;
return 0;
}