BZOJ 3932 [CQOI2015]任务查询系统 - 差分 + 主席树

Solution

差分就好了, 在$s_i$ 的点+1, $e_i + 1$ 的点 - 1。

查询的时候注意$l == r$ 要返回 $k * b[l]$ ,而不是$sum[node] $因为当前位置的个数可能大于$k$

最后再心疼自己因为神奇建树挂死2333, 被大佬喷了(

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rd read()
 5 #define ll long long
 6 using namespace std;
 7 
 8 const int N = 2e5 + 1e3;
 9 
10 int n, m, num;
11 int b[N], tot, nd_num;
12 int lson[N * 50], rson[N * 50], root[N << 2], cnt[N * 50];
13 ll lastans = 1, sum[N * 50];
14 
15 struct node {
16     int d, pos, x;
17 }a[N << 1];
18 
19 int read() {
20     int X = 0 , p = 1; char c= getchar();
21     for( ;c > '9' || c < '0'; c = getchar()) if( c == '-') p = -1;
22     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
23     return X * p;
24 }
25 
26 int cmp(const node &A, const node &B) {
27     return A.x < B.x;
28 }
29 
30 int fd(int x) {
31     return lower_bound(b + 1, b + 1 + tot, x) - b;
32 }
33 
34 
35 void change(int last, int &now, int pos, int d, int l, int r) {
36     now = ++nd_num;
37     sum[now] = sum[last] + d * b[pos];
38     cnt[now] = cnt[last] + d;
39     lson[now] = lson[last];
40     rson[now] = rson[last];
41     if(l == r) return;
42     int mid = (l + r) >> 1;
43     if(pos <= mid)
44         change(lson[last], lson[now], pos, d, l, mid);
45     else 
46         change(rson[last], rson[now], pos, d, mid + 1, r);
47 }
48 
49 ll query(int now, int k, int l, int r) {
50     if(cnt[now] < k) return sum[now];
51     if(l == r)
52         return b[l] * k;
53     int mid = (l + r) >> 1, tmp;
54     if((tmp = cnt[lson[now]]) >= k)
55         return query(lson[now], k, l, mid);
56     else 
57         return sum[lson[now]] + query(rson[now], k - tmp, mid + 1, r);
58 }
59 
60 int main()
61 {
62     n = rd; m = rd;
63     for(int i = 1; i <= n; ++i) {
64         int l = rd, r = rd, pos = rd;
65         a[++num].d = 1;
66         a[num].pos = pos;
67         a[num].x = l;
68         a[++num].d = -1;
69         a[num].pos = pos;
70         a[num].x = r + 1;
71         b[++tot] = pos;
72     }
73     sort(b + 1, b + 1 + tot);
74     tot = unique(b + 1, b + 1 + tot) - b - 1;
75     sort(a + 1, a + 1 + num, cmp);
76     for(int i = 1, j = 1; i <= m; ++i) {
77                 root[i] = root[i - 1];
78         for(; j <= num && a[j].x == i; ++j) {
79             change(root[i], root[i], fd(a[j].pos), a[j].d, 1, tot);
80         }
81     }
82     for(int i = 1; i <= m; ++i) {
83         int x = rd, A = rd, B = rd, C = rd, k;
84         k = 1 + (A * lastans + B) % C;
85         lastans = query(root[x], k, 1, tot);
86         printf("%lld\n", lastans);
87     }
88 }
View Code

 

转载于:https://www.cnblogs.com/cychester/p/9645098.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值