洛谷P3168 任務查詢系統

題意:有n個任務,第i個的存在時間是li~ri,有個權值。求t時刻第k大的權值。數組

這毒瘤...原本是前綴和 -> 主席樹,我是樹套樹...而後光榮TLE。ide

其實很裸。一開始我寫的是每一個位置維護一個權值線段樹。由於要片改點查,就用差分 + 樹狀數組搞定了。而後超時...spa

仔細思考,發現不帶修能夠直接用主席樹。code

把差分數組插入進去就好了,查詢就是前綴和。這麼一看好像主席樹就是同時對多個數組作前綴和,每一個數組就是線段樹的一個位置。blog

我沒用標記永久化,標記下傳的時候直接新建的節點。it

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <vector>
 4 
 5 typedef long long LL;
 6 const int N = 100010, lm = 1e7, M = 20000010;
 7 
 8 int n, m, tot, rt[N];
 9 int sum[M], ls[M], rs[M];
10 LL Val[M];
11 std::vector<int> d[N];
12 
13 void insert(int x, int &y, int p, int v, int l, int r) {
14     if(!y || x == y) {
15         y = ++tot;
16         sum[y] = sum[x];
17         Val[y] = Val[x];
18     }
19     if(l == r) {
20         sum[y] += v;
21         Val[y] += v * r;
22         return;
23     }
24     if(!ls[y]) {
25         ls[y] = ls[x];
26     }
27     if(!rs[y]) {
28         rs[y] = rs[x];
29     }
30     int mid = (l + r) >> 1;
31     if(p <= mid) {
32         insert(ls[x], ls[y], p, v, l, mid);
33     }
34     else {
35         insert(rs[x], rs[y], p, v, mid + 1, r);
36     }
37     sum[y] = sum[ls[y]] + sum[rs[y]];
38     Val[y] = Val[ls[y]] + Val[rs[y]];
39     return;
40 }
41 
42 LL ask(int k, int l, int r, int o) {
43     if(!o) {
44         return 0;
45     }
46     if(l == r) {
47         return 1ll * std::min(k, sum[o]) * r;
48     }
49     int mid = (l + r) >> 1;
50     if(k <= sum[ls[o]]) {
51         return ask(k, l, mid, ls[o]);
52     }
53     else {
54         return Val[ls[o]] + ask(k - sum[ls[o]], mid + 1, r, rs[o]);
55     }
56 }
57 
58 int main() {
59     scanf("%d%d", &n, &m);
60     for(int i = 1, x, y, z; i <= n; i++) {
61         scanf("%d%d%d", &x, &y, &z);
62         d[x].push_back(z);
63         d[y + 1].push_back(-z);
64     }
65 
66     // prework
67     for(int i = 1; i <= m; i++) {
68         if(!d[i].size()) {
69             rt[i] = rt[i - 1];
70             continue;
71         }
72         for(int j = 0; j < d[i].size(); j++) {
73             // d[i][j]
74             if(d[i][j] > 0) {
75                 insert(rt[i - 1], rt[i], d[i][j], 1, 1, lm);
76             }
77             else {
78                 insert(rt[i - 1], rt[i], -d[i][j], -1, 1, lm);
79             }
80         }
81     }
82 
83     LL lastans = 1;
84     for(int i = 1, t, y, z, w; i <= m; i++) {
85         scanf("%d%d%d%d", &t, &y, &z, &w);
86         lastans %= w;
87         y %= w;
88         int k = (lastans * y + z) % w + 1;
89         lastans = ask(k, 1, lm, rt[t]);
90         printf("%lld\n", lastans);
91     }
92 
93     return 0;
94 }
AC代碼
相關文章
相關標籤/搜索