有n个马, 每个马刚开始有s[i]的能量,能量上限是t[i],增长速度是v[i], 有q个操作,每次操作把询问在时刻t,l到r的马的能量和是多少,并把这个区间所有马的能量清空。
#include
using namespace std;
#define N 200020
#define LL long long
#define md (ll + rr >> 1)
#define pll pair
#define MP make_pair
#define inf 0x3f3f3f3f
int n;
int v[N];
struct seg_t {
int mx[N];
int san[N], cnt;
int rt[N], t[N];
LL sum[N*20], sumV[N*20], tot;
int ch[N*20][2];
void init() {
cnt = 0;
for(int i = 1; i <= n; ++i) {
if(v[i] == 0) t[i] = inf;
else
t[i] = ceil(mx[i] * 1.0 / v[i]);
san[++cnt] = t[i];
}
}
void add(int x) {
san[++cnt] = x;
}
int haxi(int x) {
return lower_bound(san + 1, san + cnt + 1, x) - san;
}
int update(int i, int x, int V, int M, int ll, int rr) {
int k = ++tot;
ch[k][0] = ch[i][0];
ch[k][1] = ch[i][1];
sum[k] = sum[i] + M;
sumV[k] = sumV[i] + V;
if(ll == rr) return k;
if(x <= md) ch[k][0] = update(ch[i][0], x, V, M, ll, md);
else ch[k][1] = update(ch[i][1], x, V, M, md + 1, rr);
return k;
}
void lisan() {
sort(san + 1, san + cnt + 1);
cnt = unique(san + 1, san + cnt + 1) - san - 1;
for(int i = 1; i <= n; ++i) {
t[i] = haxi(t[i]);
rt[i] = update(rt[i-1], t[i], v[i], mx[i], 1, cnt);
}
}
LL query_sum(int i, int o, int x, int ll, int rr) {
if(ll == rr) return sum[i] - sum[o];
if(x <= md) return query_sum(ch[i][0], ch[o][0], x, ll, md);
return sum[ch[i][0]] - sum[ch[o][0]] + query_sum(ch[i][1], ch[o][1], x, md + 1, rr);
}
LL query_sumV(int i, int o, int x, int ll, int rr) {
if(ll == rr) return sumV[i] - sumV[o];
if(x > md) return query_sumV(ch[i][1], ch[o][1], x, md + 1, rr);
return sumV[ch[i][1]] - sumV[ch[o][1]] + query_sumV(ch[i][0], ch[o][0], x, ll, md);
}
LL query(int l, int r, int T) {
int TT = upper_bound(san + 1, san + cnt + 1, T) - san;
--TT;
LL ret = 0;
if(TT > 0) ret += query_sum(rt[r], rt[l-1], TT, 1, cnt);
if(TT < cnt) ret += query_sumV(rt[r], rt[l-1], TT + 1, 1, cnt) * T;
return ret;
}
}T1, T2;
int t[N], L[N], R[N];
LL initSum[N];
int q;
int pre[N], ch[N][2], key[N], lazy[N];
int nodeCnt[N];
int findRoot(int u) {
while(pre[u]) u = pre[u];
return u;
}
int findL(int u) {
while(ch[u][0]) u = ch[u][0];
return u;
}
int findR(int u) {
while(ch[u][1]) u = ch[u][1];
return u;
}
int findK(int u, int k) {
while(1) {
if(nodeCnt[ch[u][0]] >= k) u = ch[u][0];
else {
k -= nodeCnt[ch[u][0]] + 1;
if(k == 0) return u;
u = ch[u][1];
}
}
return -1;
}
void push_up(int x) {
nodeCnt[x] = nodeCnt[ch[x][0]] + nodeCnt[ch[x][1]] + 1;
}
void rot(int x) {
int y = pre[x], d = ch[y][1] == x;
ch[y][d] = ch[x][!d];
pre[ch[x][!d]] = y;
ch[x][!d] = y;
pre[x] = pre[y];
pre[y] = x;
if(pre[x]) ch[pre[x]][ch[pre[x]][1]==y] = x;
push_up(y);
}
void update(int x, int t) {
if(!x) return;
key[x] = lazy[x] = t;
}
void push_down(int x) {
if(lazy[x]) {
update(ch[x][0], lazy[x]);
update(ch[x][1], lazy[x]);
lazy[x] = 0;
}
}
void P(int x) {
if(pre[x]) P(pre[x]);
push_down(x);
}
void splay(int x, int goal) {
P(x);
while(pre[x] != goal) {
int f = pre[x], ff = pre[f];
if(ff == goal) {
rot(x);
}
else if((ch[ff][1] == f) == (ch[f][1] == x))
rot(f), rot(x);
else rot(x), rot(x);
}
push_up(x);
}
int split(int u, int k, int t) {
int p = findK(u, k);
splay(p, 0);
int y = ch[p][1];
pre[ch[p][1]] = 0;
ch[p][1] = 0;
push_up(p);
if(t == 0) return p;
return y;
}
int merge(int x, int y) {
x = findRoot(x);
int t = findR(x);
y = findRoot(y);
splay(t, 0);
ch[t][1] = y;
pre[y] = t;
push_up(t);
return t;
}
bool check(int x) {
int l = findL(x);
int r = findR(x);
if(nodeCnt[x] != r - l + 1) return 0;
return 1;
}
int buildSplay(int ll, int rr, int p) {
if(ll > rr) return 0;
int x = (ll + rr) / 2;
ch[x][0] = buildSplay(ll, x - 1, x);
ch[x][1] = buildSplay(x + 1, rr, x);
pre[x] = p;
push_up(x);
return x;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
int c, d;
scanf("%d%d%d", &c, &d, &v[i]);
initSum[i] = initSum[i-1] + c;
T1.mx[i] = d - c;
T2.mx[i] = d;
}
T1.init();
T2.init();
scanf("%d", &q);
for(int i = 1; i <= q; ++i) {
scanf("%d%d%d", &t[i], &L[i], &R[i]);
}
T1.lisan();
T2.lisan();
for(int i = 1; i <= n; ++i) nodeCnt[i] = 1;
buildSplay(1, n, 0);
for(int i = 1; i <= q; ++i) {
LL ans = 0;
for(int j = L[i], x; j <= R[i]; j = x + 1) {
int p = findRoot(j);
int l = findL(p);
int r = findR(p);
if(nodeCnt[p] != r - l + 1) {
printf(" error %d %d %d\n", nodeCnt[p], l, r);
return 0;
}
if(l < L[i]) {
p = split(p, L[i] - l, 1);
}
if(r > R[i]) {
p = split(p, nodeCnt[p] - (r - R[i]), 0);
}
l = findL(p);
r = findR(p);
x = r;
if(key[p] == 0) {
ans += T1.query(l, r, t[i] - key[p]);
ans += initSum[r] - initSum[l-1];
}
else {
ans += T2.query(l, r, t[i] - key[p]);
}
if(l != L[i]) p = merge(l - 1, p);
key[p] = lazy[p] = t[i];
}
printf("%lld\n", ans);
}
return 0;
}