因為有m[i]的限制,不能用 線段樹搞。考慮每個魔法機關,因為d = m[i] / r[i]是固定的,當一段時間間隔 t 大于d時,答案加上m[i],否則就是t * r[i],是以變成考慮怎麼維護每個魔法機關的所有時間間隔t。
離線所有操作,儲存在a 和 b數組裡面,a 按照 l 排序,b 按照 r 排序,L指針是a數組的,R指針是b數組的。從左到右枚舉每個魔法機關,用treap維護時間間隔。插入删除的時候注意。另外還要注意r[i] == 0的情況(RE了好多發 -_-|| )
看這裡
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#pragma comment(linxer, "/STACK:102400000,102400000")
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define ls i << 1
#define rs ls | 1
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 2000010
#define M 200020
int getint(){
char c = getchar(); int ret = ;
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') ret = ret* + c - '0', c = getchar();
return ret;
}
struct node{
int t, l, r, id;
void input(){
t = getint(); l = getint(); r = getint();
}
};
bool cmp1(const node &a, const node &b){
return a.l < b.l || (a.l == b.l && a.r < b.r);
}
bool cmp2(const node &a, const node &b){
return a.r < b.r || (a.r == b.r && a.l < b.l);
}
node a[M], b[M];
int ch[N][], rand_val[N], sz[N], key[N], tot;
LL sum[N];
int s[M], mi[M], r[M];
set<pii > S;
set<pii >::iterator it, itt;
queue<int> q;
int creat(int val){
tot = q.front(); q.pop();
ch[tot][] = ch[tot][] = ;
rand_val[tot] = rand();
key[tot] = val;
sum[tot] = val;
sz[tot] = ;
return tot;
}
int cmp(int x, int val){
if(key[x] == val) return -;
return val < key[x] ? : ;
}
void push_up(int x){
sz[x] = sz[ch[x][]] + sz[ch[x][]] + ;
sum[x] = sum[ch[x][]] + sum[ch[x][]] + key[x];
}
void rot(int &x, int d){
int k = ch[x][!d];
ch[x][!d] = ch[k][d];
ch[k][d] = x;
push_up(x);
push_up(k);
x = k;
}
void insert(int &x, int val){
if(x == ){
x = creat(val);
return ;
}
int d = cmp(x, val);
if(d == -)
d = ;
insert(ch[x][d], val);
if(rand_val[ch[x][d]] > rand_val[x]) rot(x, d ^ );
push_up(x);
}
void del(int &x, int val) {
if(x == ) return;
int d = cmp(x, val);
if(d == -) {
if(!ch[x][]) q.push(x), x = ch[x][];
else if(!ch[x][]) q.push(x), x = ch[x][];
else {
int d2 = rand_val[ch[x][]] > rand_val[ch[x][]]? : ;
rot(x, d2);
del(ch[x][d2], val);
}
}
else del(ch[x][d], val);
if(x) push_up(x);
}
LL query1(int x, int val){ //查詢小于等于val的sum值
if(!x) return ;
int d = cmp(x, val);
if(d == )
return query1(ch[x][], val);
else
return sum[ch[x][]] + key[x] + query1(ch[x][], val);
}
int query2(int x, int val){ //查詢大于val的sz值
if(!x) return ;
int d = cmp(x, val);
if(d == )
return sz[ch[x][]] + + query2(ch[x][], val);
else
return query2(ch[x][], val);
}
void output(int x){
if(!x) return ;
output(ch[x][]);
printf("%d ", key[x]);
output(ch[x][]);
}
int main(){
for(int i = ; i < N; ++i)
q.push(i);
int n;
n = getint();
for(int i = ; i <= n; ++i){
s[i] = getint(), mi[i] = getint(), r[i] = getint();
}
int m, pre = ;
m = getint();
for(int i = ; i <= m; ++i){
a[i].input();
a[i].id = i;
pre = a[i].t;
b[i] = a[i];
}
sort(a + , a + + m, cmp1);
sort(b + , b + + m, cmp2);
int L = , R = , rt = ;
LL ans = ;
S.insert(MP(, ));
for(int i = ; i <= n; ++i){
// if(i == n){
// output(rt); puts("");
// }
while(L <= m && a[L].l <= i){
it = S.lower_bound(MP(a[L].t, a[L].id));
itt = it;
--it;
if(itt != S.end()){
int tmp = (*itt).first - (*it).first;
del(rt, tmp);
insert(rt, (*itt).first - a[L].t);
}
insert(rt, a[L].t - (*it).first);
S.insert(MP(a[L].t, a[L].id));
L++;
}
while(R <= m && b[R].r < i){
itt = S.lower_bound(MP(b[R].t, b[R].id));
it = itt;
++itt;
--it;
if(itt == S.end()){
del(rt, b[R].t - (*it).first);
S.erase(MP(b[R].t, b[R].id));
R++;
continue;
}
else{
del(rt, (*itt).first - b[R].t);
del(rt, b[R].t - (*it).first);
insert(rt, (*itt).first - (*it).first);
}
S.erase(MP(b[R].t, b[R].id));
R++;
}
int tmp = -;
if(S.size() > ){
it = S.begin();
++it;
tmp = (*it).first;
ans += min((LL)mi[i], L * tmp * r[i] + s[i]);
del(rt, tmp);
if(r[i] > )
ans += L * query1(rt, mi[i] / r[i]) * r[i] + L * query2(rt, mi[i] / r[i]) * mi[i];
insert(rt, tmp);
}
}
printf("%lld\n", ans);
return ;
}