题意:
给你
x1, x2, y1, y2, a1, a2, b1, b2, c1, c2, m1, m2;
推导出接下来的每一项x和y
Xi = (a1 * Xi-1 + b1 * Xi-2 + c1) % m1
Yi = (a2 * Yi-1 + b2 * Yi-2 + c2) % m2
Ri = max(Xi, Yi)
Li = min(Xi, Yi)
n次操作 往序列里面(初始为空)加入 Li ~ Ri (Ri - Li + 1) 个数 求当前中位数为多少 偶数个取中间偏前的数字
题目链接:
https://ac.nowcoder.com/acm/contest/887/E
题解:
先对所有的L, R 离散化
建两个树状数组
然后二分枚举中位数
树状数组求和前面有多少个数字
第一个bit1 树状数组的求一定不对 因为如果前面有多个L 比 R 多
那么我们就要把R在后面给他加回来
所以bit2记录的是前面有多少个L
AC_code:
#include<bits/stdc++.h>
using namespace std;
#define maxn 400010
#define ll long long
int n, x[maxn], y[maxn], l[maxn], r[maxn];
ll a1,a2, b1, b2, c1, c2, m1, m2;
int z[maxn<<1], cnt;
ll bit1[maxn], bit2[maxn];
int lowbit(int x) {
return x&(-x);
}
void add(ll bit[], int p, int x) {
for(int i = p; i <= cnt; i += lowbit(i)) {
bit[i] += x;
}
}
ll query(ll bit[], int p) {
ll ans = 0;
for(int i = p; i > 0; i -= lowbit(i)) {
ans += bit[i];
}
return ans;
}
int main() {
cin>>n;
cin>> x[1] >> x[2] >> a1 >> b1 >> c1 >> m1;
cin>> y[1] >> y[2] >> a2 >> b2 >> c2 >> m2;
for(int i = 1; i <= n; i++) {
if(i > 2) {
x[i] = (a1 * x[i-1] + b1 * x[i-2] + c1) % m1;
y[i] = (a2 * y[i-1] + b2 * y[i-2] + c2) % m2;
}
l[i] = min(x[i], y[i]) + 1;
r[i] = max(x[i], y[i]) + 1;
z[++cnt] = l[i];
z[++cnt] = r[i] + 1;
}
sort(z+1, z+cnt+1);
cnt = unique(z+1, z+cnt+1) - z - 1;
ll t = 0;
for(int i = 1; i <= n; i++){
t += r[i] - l[i] + 1;
int L = lower_bound(z+1, z+cnt+1, l[i]) - z;
int R = lower_bound(z+1, z+cnt+1, r[i]+1) - z;
add(bit1, L, -l[i]);
add(bit1, R, r[i]+1);
add(bit2, L, 1);
add(bit2, R, -1);
L = 1, R = 1e9;
while(L < R){
int mid = (L + R) / 2;
int pos = upper_bound(z+1, z+cnt+1, mid) -z - 1;
ll tmp = query(bit1, pos) + query(bit2, pos) * (mid + 1);
if(tmp < (t+1)/2){
L = mid + 1;
}else {
R = mid;
}
}
printf("%d\n", L);
}
return 0;
}