传送门
题意:给你n个区间,每次往你现有的数中加上l,l+1,.....,r-1,r这些数,求现在所有数的中位数
解:区间的范围很大,我们肯定需要离散化,解法也很直观,肯定是线段树维护吗,就维护区间出现点的个数,这样我们query的时候就可以根据数量一直走到叶子节点,求出答案,所以我们每个叶子节点就是代表一段小区间了。这里算是一个小技巧吧,我们把所有的区间都看成是左开右闭的,这样叶子节点的区间就不怕冲突了。比如给出区间[1,3],[2,7],我们将其看成[1,4),[2,8);经过我们离散化会得到 1,2,4,8 ,那我们线段树的叶子节点所代表的区间就是[1,2),[2,4),[4,8).
#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define SZ(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define drep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const double pi=acos(-1.0);
const double eps=1e-9;
const int maxn=4e5+5;
//il int Add(int x,int y) {return x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll x,int y) {return x*y>=mod?x*y%mod:x*y;}
int X[maxn],Y[maxn],A1,A2,B1,B2,C1,C2,M1,M2,N;
int L[maxn],R[maxn],s[maxn<<2];
struct node{
int l,r,lz;
ll num;
bool fg;
}sum[maxn<<3];
il void pushup(int rt){
sum[rt].num=sum[rt<<1].num+sum[rt<<1|1].num;
}
il void pushdown(int rt){
if(sum[rt].lz){
sum[rt<<1].lz+=sum[rt].lz;
sum[rt<<1|1].lz+=sum[rt].lz;
sum[rt<<1].num+=1LL*sum[rt].lz*(sum[rt<<1].r-sum[rt<<1].l);
sum[rt<<1|1].num+=1LL*sum[rt].lz*(sum[rt<<1|1].r-sum[rt<<1|1].l);
sum[rt].lz=0;
}
}
il void build(int l,int r,int rt){
if(l==r){
sum[rt].l=s[l],sum[rt].r=s[l+1];
sum[rt].fg=1;
return ;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
sum[rt].l=sum[rt<<1].l,sum[rt].r=sum[rt<<1|1].r;
}
il void update(int L,int R,int rt){
if(L<=sum[rt].l && R>=sum[rt].r){
sum[rt].num+=sum[rt].r-sum[rt].l;
sum[rt].lz++;
return ;
}
pushdown(rt);
if(L<sum[rt<<1].r) update(L,R,rt<<1);
if(R>sum[rt<<1|1].l) update(L,R,rt<<1|1);
pushup(rt);
}
il int query(int rt,ll cnt){
if(sum[rt].fg){
ll tp=sum[rt].num/(sum[rt].r-sum[rt].l);
if(cnt%tp==0) return sum[rt].l+(cnt/tp)-1;
else return sum[rt].l+(cnt/tp);
}
pushdown(rt);
if(cnt<=sum[rt<<1].num) return query(rt<<1,cnt);
else return query(rt<<1|1,cnt-sum[rt<<1].num);
}
int main(){
std::ios::sync_with_stdio(0);
scanf("%d",&N);
scanf("%d%d%d%d%d%d",&X[1],&X[2],&A1,&B1,&C1,&M1);
scanf("%d%d%d%d%d%d",&Y[1],&Y[2],&A2,&B2,&C2,&M2);
int tot=0;
for(int i=1;i<=N;++i){
if(i>=3){
X[i]=(1LL*A1*X[i-1]+1LL*B1*X[i-2]+C1)%M1;
Y[i]=(1LL*A2*Y[i-1]+1LL*B2*Y[i-2]+C2)%M2;
}
L[i]=min(X[i],Y[i])+1;
R[i]=max(X[i],Y[i])+2;//左闭右开
s[++tot]=L[i],s[++tot]=R[i];
}
sort(s+1,s+tot+1);
tot=unique(s+1,s+tot+1)-(s+1);
build(1,tot-1,1);
ll all=0;
for(int i=1;i<=N;++i){
update(L[i],R[i],1);
all+=R[i]-L[i];
printf("%d\n",query(1,(all+1)/2));
}
return 0;
}