牛客多校第七场E Find the median
题意:每次在一个空区间内加入[L,R]区间内所有的数,然后问每次加入后的中位数是什么。
题解:一道线段树的题目。
A:线段树的叶子节点维护了一个区间,这个区间是[L,R+1),为什么是这区间?(因为这样能不重不漏的包含所有的区间,每次查询的时候也不会漏掉,自己画一颗线段树基本能明白了)。
B:然后查询的时候,记录一下这个区间的个数,然后减去这个区间内有能最大的容纳的不同的个数,最后相减得到答案。
闲话:太久没写线段树,导致这题A得太慢了。以后上来就找线段树的题目吧。
代码:
#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
const int mx = 5e5 + 7;
typedef long long ll;
struct node {
ll v;
ll index;
ll c;
ll lazy;
}tree[mx<<3];
int n;
ll x[mx], y[mx], l[mx], r[mx];
ll qc[mx << 3];
ll a, b, c, mo;
void pushup(int id) {
tree[id].c = tree[id << 1].c + tree[id << 1 | 1].c;
}
void pushdown(int id) {
if (tree[id].lazy) {
tree[id << 1].lazy += tree[id].lazy;
tree[id << 1 | 1].lazy += tree[id].lazy;
tree[id << 1].c += (1LL * tree[id<<1].v * tree[id].lazy);
tree[id << 1|1].c += (1LL * tree[id<<1|1].v * tree[id].lazy);
tree[id].lazy = 0;
}
}
void build(int id, int l, int r) {
if (l == r) {
tree[l].index = id;
tree[id].v = qc[l] - qc[l - 1];
return;
}
int mid = (l + r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid + 1, r);
tree[id].v = tree[id << 1].v + tree[id << 1 | 1].v;
}
void update(int id, int l, int r,int rl,int rr,int lz) {
if (rl < l && rr >= r) { //??????
tree[id].lazy += lz;
tree[id].c += (1LL * lz * tree[id].v);
return;
}
if (rl >= r || rr < l) return;
pushdown(id);
int mid = (l + r) >> 1;
update(id << 1, l, mid, rl, rr, lz);
update(id << 1 | 1, mid + 1, r, rl, rr, lz);
pushup(id);
}
ll query(int id, int l, int r,int rl,int rr) {
if (rl <= l && rr >= r) return tree[id].c;
if (rl > r || rr < l) return 0;
pushdown(id);
int m = (l + r) / 2;
ll ans = 0;
ans += query(id << 1, l, m, rl, rr) + query(id << 1 | 1, m + 1, r, rl, rr);
return ans;
}
int main() {
scanf("%d", &n);
scanf("%lld%lld%lld%lld%lld%lld", &x[1], &x[2], &a, &b, &c, &mo);
for (int i = 3; i <= n; i++)
x[i] = (a * x[i - 1] + b * x[i - 2] + c) % mo;
scanf("%lld%lld%lld%lld%lld%lld", &y[1], &y[2], &a, &b, &c, &mo);
for (int i = 3; i <= n; i++)
y[i] = (a * y[i - 1] + b * y[i - 2] + c) % mo;
ll cnt = 0;
for (int i = 1; i <= n; i++) {
l[i] = min(x[i], y[i]) + 1;
r[i] = max(x[i], y[i]) + 1;
qc[++cnt] = l[i];
qc[++cnt] = r[i] + 1;
}
sort(1 + qc, 1 + qc +cnt);
cnt = unique(qc + 1, qc + 1 +cnt) - qc - 1;
ll num = 0;
build(1, 1, cnt);
for (int i = 1; i <= n; i++) {
num += r[i] - l[i] + 1;
int f1 = lower_bound(qc + 1, qc + 1 + cnt, l[i]) - qc;
int f2 = lower_bound(qc + 1, qc + 1 + cnt, r[i] + 1) - qc;
update(1, 1, cnt, f1, f2, 1);
int L = 1, R = cnt, mid;
ll ans = 0, m = (num + 1) / 2;
while (L < R) {
mid = (L + R) >> 1;
ans = query(1, 1, cnt, 1, mid);
if (ans >= m) R = mid;
else L = mid + 1;
}
ans = query(1, 1, cnt, 1, L);
ll trans = ans - m;
ll re = tree[tree[L].index].c / tree[tree[L].index].v;
ll ret = qc[L] - trans / re - 1;
printf("%lld\n", ret);
}
return 0;
}