bzoj3932
3932: [CQOI2015]任务查询系统
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3225 Solved: 1038
[Submit][Status][Discuss]
Description
最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。超级计算机中的
任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行
),其优先级为Pi。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。调度系统会经常向
查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个
)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先
级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。
Input
输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。接下来m行,每行包含三个空格
分开的正整数Si、Ei和Pi(Si≤Ei),描述一个任务。接下来n行,每行包含四个空格分开的整数Xi、Ai、Bi和Ci,
描述一次查询。查询的参数Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci计算得到。其中Pre表示上一次查询的结果,
对于第一次查询,Pre=1。
Output
输出共n行,每行一个整数,表示查询结果。
Sample Input
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
1 2 6
2 3 3
1 3 2
3 3 4
3 1 3 2
1 1 3 4
2 2 4 3
Sample Output
2
8
11
8
11
HINT
样例解释
K1 = (1*1+3)%2+1 = 1
K2 = (1*2+3)%4+1 = 2
K3 = (2*8+4)%3+1 = 3
对于100%的数据,1≤m,n,Si,Ei,Ci≤100000,0≤Ai,Bi≤100000,1≤Pi≤10000000,Xi为1到n的一个排列
Source
主席树
差分思想 然后对于每个任务分成两个 一次减一次加 主席树插入具体看代码 注意每次查询的时候必须用l和r 因为不用的话可能同一个任务有很多种 无法通过size判断结束 如果已经走到了l==r 不用lr的话就可能继续走下去 还有rank可能比size小
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 200010; int n, m, cnt; ll pre = 1; int root[N], size[N * 20], lc[N * 20], rc[N * 20]; ll sum[N * 20]; struct data { int p, t; }; map<int, int> rnk; vector<int> p; vector<int> t[N]; namespace tree { void build(int l, int r, int &x) { x = ++cnt; if(l == r) return; int mid = (l + r) >> 1; build(l, mid, lc[x]); build(mid + 1, r, rc[x]); } void update(int l, int r, int &x, int last, int pos, int delta, int f) { x = ++cnt; lc[x] = lc[last]; rc[x] = rc[last]; size[x] = size[last] + f; sum[x] = sum[last] + delta; if(l == r) return; int mid = (l + r) >> 1; if(pos <= mid) update(l, mid, lc[x], lc[last], pos, delta, f); else update(mid + 1, r, rc[x], rc[last], pos, delta, f); } ll query(int l, int r, int x, int rank) { if(rank >= size[x]) return sum[x]; if(l == r) return sum[x] * rank / size[x]; int t = size[lc[x]], mid = (l + r) >> 1; if(t >= rank) return query(l, mid, lc[x], rank); else return query(mid + 1, r, rc[x], rank - t) + sum[lc[x]]; } } using namespace tree; int main() { // freopen("cqoi15_query.in", "r", stdin); // freopen("cqoi15_query.out", "w", stdout); scanf("%d%d", &m, &n); for(int i = 1; i <= m; ++i) { int s, e, P; scanf("%d%d%d", &s, &e, &P); p.push_back(P); t[s].push_back(P); t[e + 1].push_back(-P); } sort(p.begin(), p.end()); p.erase(unique(p.begin(), p.end()), p.end()); for(int i = 0; i < p.size(); ++i) rnk[p[i]] = i + 1; build(1, m, root[0]); for(int i = 1; i <= n; ++i) { if(t[i].empty()) { root[i] = root[i - 1]; continue; } update(1, m, root[i], root[i - 1], rnk[abs(t[i][0])], t[i][0], (t[i][0] > 0 ? 1 : -1)); for(int j = 1; j < t[i].size(); ++j) { int node = 0; // printf("pos=%d t[i][j]=%d\n", rnk[abs(t[i][j])], t[i][j]); update(1, m, node, root[i], rnk[abs(t[i][j])], t[i][j], (t[i][j] > 0 ? 1 : -1)); root[i] = node; } } for(int i = 1; i <= n; ++i) { int x, a, b, c; scanf("%d%d%d%d", &x, &a, &b, &c); int k = 1 + ((ll)a * pre + (ll)b) % (ll)c; pre = query(1, m, root[x], k); printf("%lld\n", pre); } // fclose(stdin); fclose(stdout); return 0; }