将一个任务拆成两个点,排序后查询某个点上k小值的和
用可持久化线段树做一做就可以了
TAT以后写主席树一定要离散。。RE不止。。(其实是爆内存了。。)
特别注意容易写渣的地方是引用root[]数组。。
我怎么会直接就引用了下标呢QAQ。。
不长记性!
#include
#define maxn 500010
using namespace std;
int n, m;
struct operation{
int s, tp, v, cnt;
bool operator<(const operation& k)const{
return s < k.s;
}
}q[maxn];
#define M 20000010
int lc[M], rc[M], val[M], root[maxn], size;
long long sum[M];
int build(int l, int r){
int cur = ++ size;
if(l == r)return cur;
int mid = l + r >> 1;
lc[cur] = build(l, mid);
rc[cur] = build(mid+1, r);
return cur;
}
long long hs[maxn];
int Insert(int rt, int l, int r, int pos, int v){
int cur = ++ size;
sum[cur] = sum[rt] + v * hs[pos];
lc[cur] = lc[rt], rc[cur] = rc[rt], val[cur] = val[rt] + v;
if(l == r)return cur;
int mid = l + r >> 1;
if(pos <= mid)lc[cur] = Insert(lc[rt], l, mid, pos, v);
else rc[cur] = Insert(rc[rt], mid+1, r, pos, v);
return cur;
}
long long ask(int rt, int l, int r, int kth){
if(l == r)return min(val[rt], kth) * hs[l];
int mid = l + r >> 1;
if(val[lc[rt]] <= kth)
return sum[lc[rt]] + ask(rc[rt], mid+1, r, kth - val[lc[rt]]);
return ask(lc[rt], l, mid, kth);
}
int h[maxn];
int main(){
scanf("%d%d", &m, &n);
int s, e, p, tot = 0, mx = 0;
for(int i = 1; i <= m; i ++){
scanf("%d%d%d", &s, &e, &p);
q[++ tot].s = s;
q[tot].tp = 1;
q[tot].v = p;
q[++ tot].s = e + 1;
q[tot].tp = -1;
q[tot].v = p;
hs[++ mx] = p;
}
sort(hs + 1, hs + 1 + mx);
mx = unique(hs + 1, hs + 1 + mx) - hs - 1;
for(int i = 1; i <= tot; i ++)
q[i].v = lower_bound(hs + 1, hs + 1 + mx, q[i].v) - hs;
sort(q + 1, q + 1 + tot);
root[0] = build(1, mx);
int j = 1, cnt = 0;
for(int i = 1; i <= tot; i = j){
++ cnt;
root[cnt] = root[cnt - 1];
for(; j <= tot && q[i].s == q[j].s; j ++)
root[cnt] = Insert(root[cnt], 1, mx, q[j].v, q[j].tp);
h[cnt] = q[i].s;
}
long long pre = 1;
int x, a, b, c;
for(int i = 1; i <= n; i ++){
scanf("%d%d%d%d", &x, &a, &b, &c);
int k = 1 + ((long long)a * pre + b) % c;
int y = lower_bound(h + 1, h + 1 + cnt, x) - h;
while(y && h[y] > x)y --;
printf("%lld\n", pre = ask(root[y], 1, mx, k));
}
return 0;
}