搞不来莫比乌斯反演的我只好搞这个了 结果把自己整的要死 Orz
首先把优先级离散化 然后开可持久化线段树 区间为优先级的区间
把每个任务做成两个 类似于维护差分数组的感觉 然后一个一个插入到可持久化线段树里面去
注意对任务总数的增加 及 减少
注意任务有重复 所以如果区间长度为1时 返回的是 和/数量*k
一晚上就搞这个了Orz
果然像我这样的人最好早点滚粗
#include #include #include #include #include #include #include #define SF scanf #define PF printf using namespace std; typedef long long LL; const int MAXN = 100000; int n, MAX, tot, N, m; struct Node { int ls, rs, cnt; LL sum; } ; struct Task { int x, p, op; bool operator < (const Task &t) const { return x < t.x; } } A[MAXN*2+10]; void Make(int x, int p, int op) { tot++; A[tot].x = x; A[tot].p = p; A[tot].op = op; } int pri[MAXN+10], rt[MAXN+10]; bool Table; struct Seg_Tree { Node tree[MAXN * 50 + 10]; int ncnt; void ins(int &i, int val, int op, int L, int R) { tree[++ncnt] = tree[i]; i = ncnt; tree[i].cnt += op; tree[i].sum += 1LL * op * pri[val]; if(L == R) return ; int mid = L + ((R-L) >> 1); if(val <= mid) ins(tree[i].ls, val, op, L, mid); else ins(tree[i].rs, val, op, mid+1, R); } int GetK(int i, int k) { int L = 1, R = N; while(L < R) { int mid = L + ((R-L) >> 1); if(k <= tree[tree[i].ls].cnt) i = tree[i].ls, R = mid; else { k -= tree[tree[i].ls].cnt; i = tree[i].rs; L = mid+1; } } return L; } LL query(int i, int pos, int L, int R, int k) { if(R < pos) return tree[i].sum; if(L == R && R == pos) return tree[i].sum / tree[i].cnt * k; int mid = L + ((R-L) >> 1); LL ret = query(tree[i].ls, pos, L, mid, min(tree[tree[i].ls].cnt, k)); if(mid+1 <= pos) ret += query(tree[i].rs, pos, mid+1, R, k-tree[tree[i].ls].cnt); return ret; } } seg; int main() { SF("%d%d", &n, &m); MAX = m+1; for(int i = 1; i <= n; i++) { int s, t, p; SF("%d%d%d", &s, &t, &p); Make(s, p, 1); Make(t+1, p, -1); pri[i] = p; } sort(A+1, A+1+tot); sort(pri+1, pri+1+n); N = unique(pri+1, pri+1+n) - (pri+1); for(int i = 1; i <= tot; i++) A[i].p = lower_bound(pri+1, pri+1+N, A[i].p) - pri; for(int i = 1; i <= tot; i++) { for(int k = A[i-1].x+1; k <= A[i].x; k++) rt[k] = rt[k-1]; seg.ins(rt[A[i].x], A[i].p, A[i].op, 1, N); } for(int i = A[tot].x+1; i <= MAX; i++) rt[i] = rt[i-1]; LL last = 1; for(int i = 1; i <= m; i++) { int x, A, B, C, k; SF("%d%d%d%d", &x, &A, &B, &C); k = 1LL * (1LL * A * last % C + B) % C + 1; if(k > seg.tree[rt[x]].cnt) last = seg.tree[rt[x]].sum; else if(k == 0) last = 0; else { int pos = seg.GetK(rt[x], k); last = seg.query(rt[x], pos, 1, N, k); } cout << last << '\n'; } } /* 4 3 1 2 6 2 3 3 1 3 2 3 3 4 3 1 3 2 1 1 3 4 2 2 4 3 */