题意:
你一开始有一个空序列,每次在你的序列中塞入l-r中所有的值,并且问你现在你的序列的中位数是什么。
题解:
二分+线段树TLE。。。重算一遍才发现忘记将lower_bound的复杂度算进去了。
需要用两个数组维护:sum[]表示区间内值的个数,flag[]是延时标记,同时它如果延到叶子结点了是不会清空的,那么在这里就可以表示这个位置出现了多少次来用。我们将所有输入离散化,这时候就有一个问题:我怎么知道我要查询的位置出现了几次?它可以看做是和它左边第一个在输入中出现过的数字是相等的。为什么?因为如果这个数不可能是中位数,那么我们就不会查到他,如果它可能是,那么我们线段树是按照从小到大建树的,那么肯定会查到它或者它左边的值。
对于为什么rig要+2,因为在线段树中,如果直接维护离散化区间的值,就比如说原数组第三个位置是3,第4个位置是5,第5个位置是6,那么我们如果加入3-6,对于离散化的结果是不会变的,但是线段树里面就少了一个4的内容。但是如果直接维护a[r+1]-a[l]+1的话,那么push_down时会多加一次,所以我们直接用r+2,这样不会错
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pa pair<ll,ll>
const int N=4e5+5;
ll x[N],y[N],a1,b1,c1,m1,a2,b2,c2,m2;
ll a[N*2],flag[N*2*4],sum[N*2*4],num[N*2*4];
void push_down(int l,int r,int root)
{
if(!flag[root])
return ;
int mid=l+r>>1;
sum[root<<1]+=(ll)(a[mid+1]-a[l])*flag[root];
sum[root<<1|1]+=(ll)(a[r+1]-a[mid+1])*flag[root];
flag[root<<1]+=flag[root];
flag[root<<1|1]+=flag[root];
flag[root]=0;
}
void update(int l,int r,int root,int ql,int qr)
{
if(l>=ql&&r<=qr)
{
sum[root]+=(ll)a[r+1]-a[l];
flag[root]++;
return ;
}
push_down(l,r,root);
int mid=l+r>>1;
if(mid>=ql)
update(l,mid,root<<1,ql,qr);
if(mid<qr)
update(mid+1,r,root<<1|1,ql,qr);
sum[root]=sum[root<<1]+sum[root<<1|1];
}
ll query(int l,int r,int root,ll pos)
{
if(l==r)
{
//printf("**:a[l]:%d %d\n",a[l],a[l]+(pos-1)/num[root]);
return a[l]+(pos-1)/flag[root];
}
int mid=l+r>>1;
push_down(l,r,root);
if(sum[root<<1]<pos)
return query(mid+1,r,root<<1|1,pos-sum[root<<1]);
else
return query(l,mid,root<<1,pos);
}
int all,le[N],rig[N];
ll all_num;
int main()
{
int n;
scanf("%d",&n);
scanf("%lld%lld%lld%lld%lld%lld",&x[1],&x[2],&a1,&b1,&c1,&m1);
scanf("%lld%lld%lld%lld%lld%lld",&y[1],&y[2],&a2,&b2,&c2,&m2);
a[1]=x[1]+1,a[2]=x[2]+1,a[3]=y[1]+1,a[4]=y[2]+1;
for(int i=3;i<=n;i++)
x[i]=(x[i-1]*a1+x[i-2]*b1+c1)%m1,y[i]=(y[i-1]*a2+y[i-2]*b2+c2)%m2;
for(int i=1;i<=n;i++)
{
le[i]=min(x[i],y[i])+1;
rig[i]=max(x[i],y[i])+2;
a[i*2-1]=le[i],a[i*2]=rig[i];
}
sort(a+1,a+1+n*2);
all=unique(a+1,a+1+n*2)-a-1;
a[all+1]=a[all]+1;
for(int i=1;i<=n;i++)
le[i]=lower_bound(a+1,a+1+all,le[i])-a,rig[i]=lower_bound(a+1,a+1+all,rig[i])-a;
int last=0;
for(int i=1;i<=n;i++)
{
all_num+=(ll)a[rig[i]]-a[le[i]];
update(1,all,1,le[i],rig[i]-1);
printf("%d\n",query(1,all,1,(all_num+1)/2));
}
return 0;
}
/*
5
3 1 4 1 5 9
2 7 1 8 2 9
*/