F Energy stones
题意是,有$n$个石头,每个石头有初始能量$E_i$,每秒能量增长$L_i$,以及能量上限$C_i$,有$m$个收能量的时间点,每次把区间$\left[S_i, T_i\right]$石头的能量都给收掉,石头的能量都置零重新开始增长。问最后收了多少能量。 看完题解觉得好有道理...我好菜... 考虑每个石头在多少个时间点收能量,然后每次收的能量就和这些时间点的时间间隔有关。 若时间间隔大于等于$\dfrac {C_i}{L_i}$,那么这一段对答案的贡献就是$C_i$了,统计有多少这样的段即可。 若时间间隔小于$\dfrac {C_i}{L_i}$那么对答案的贡献就是时间长度$t \times L_i$。 用两个权值树状数组可以维护对应时间长度的和及个数。 时间点可以用set维护。从前到后遍历,遇到一个$S_i$就把对应是时间加入,遇到一个$T_i + 1$就把时间删去,同时维护树状数组即可。感觉看代码就很好懂? #include <bits/stdc++.h> #define ll long long using namespace std; const int N = 2e5 + 7; int n, m; ll E[N], C[N], L[N]; set<int> st; vector<int> G[N]; struct BIT { ll tree1[N], tree2[N];