在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位。
毁灭者的核心技能之一,叫做魔法吸收(Absorb Mana):
现在让我们来考虑下面的问题:
假设你拥有 n 个魔法单位,他们从左到有站在一行,编号从 1 到 n。 每个单位拥有三项属性:
si: 初始法力。
mi: 最大法力上限。
ri: 每秒中法力回复速度。
现在你操纵一个毁灭者,有 m 个操作,t l r,表示时刻 t,毁灭者对所有编号从 l 到 r 的单位,使用了魔法吸收。操作按照时间顺序给出,计算毁灭者一共吸收了多少法力。
输入数据的第一行有一个整数 n(1 ≤ n ≤105) — 你的魔法单位的数目。
接下来的 n 行,每行有三个整数 si, mi, ri(0 ≤ si ≤ mi ≤ 105, 0 ≤ ri ≤ 105) 描述一个魔法单位。
接下来一行又一个整数 m(1 ≤ m ≤ 105), — 操作的数目。
接下来的 m 行,每行描述一个操作 t, l, r(0 ≤ t ≤ 109, 1 ≤ l ≤ r ≤ n),t 非降。
输出一行一个整数表示毁灭者一共吸收了多少法力。
5 0 10 1 0 12 1 0 20 1 0 12 1 0 10 1 2 5 1 5 19 1 5
83
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int sum[100010<<2]; int m[100000],ri[100000],t[100010<<2]; const long long MOD=1000000007; void pushup(int root) { sum[root]=sum[root<<1]+sum[root<<1|1]; } void build(int l,int r,int root) { if(r==l){ scanf("%d%d%d",&sum[root],&m[l],&ri[l]); t[l]=0; return ; } int mid=(l+r)>>1; build(l,mid,root<<1); build(mid+1,r,root<<1|1); pushup(root); } void recover(int time,int L,int R,int l,int r,int root) { if(l==r&&(l>=L&&l<=R)){ int temp=(time-t[l])*ri[l]; if(sum[root]+temp>m[l]) sum[root]=m[l]; else sum[root]+=temp; return ; } int mid=(l+r)>>1; if(L<=mid) recover(time,L,R,l,mid,root<<1); if(R>mid) recover(time,L,R,mid+1,r,root<<1|1); pushup(root); } long long query(int L,int R,int l,int r,int root) { if(L<=l&&R>=r) return sum[root]; int mid=(l+r)>>1; long long ans=0; if(L<=mid) ans=query(L,R,l,mid,root<<1); if(R>mid) ans+=query(L,R,mid+1,r,root<<1|1); return ans; } void clea(int time,int L,int R,int l,int r,int root) { if(l==r&&(l>=L&&l<=R)){ t[l]=time; sum[root]=0; return ; } int mid=(l+r)>>1; if(L<=mid) clea(time,L,R,l,mid,root<<1); if(R>mid) clea(time,L,R,mid+1,r,root<<1|1); pushup(root); } int main() { int n; memset(t,0,sizeof(t)); scanf("%d",&n); build(1,n,1); int tm; scanf("%d",&tm); long long ans=0; for(int i=1;i<=tm;i++){ int time,l,r; scanf("%d%d%d",&time,&l,&r); recover(time,l,r,1,n,1); ans=(ans+query(l,r,1,n,1))%MOD; clea(time,l,r,1,n,1); } printf("%lld",ans); return 0; }