2019牛客暑期多校训练营(第七场) E 线段树+离散化

题目传送门

题意:按照一定的公式给出若干个$<l,r>$,每次往一个序列中加上l到r的数字,并输出中位数。

思路:需要将每个$区间$离散化,比如把$[1,2]$变成$[1,3)$,也就是$[1,2)$和$[2,3)$,这样做才能完整的表达区间,否则如[2,2]这样的区间就会出现问题。

  所以我们将每一个$[l,r+1)$离散化,设$(x)$代表x离散化后的数字,每次更新的时候,右区间应该是$(r+1)-1$。比如原来只有一个区间$[2,3]$,我们表示成$[2,4)$,离散化后我们更新的区间是$[1,1]$,加的数字的个数是$ve[2]-ve[1]$,ve是原数组。

  查询和更新思路一样。

#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
#define pb(a)  push_back(a)
#define rep(i,x,n) for(int i=x;i<=n;++i)
#define dep(i,n,x) for(int i=n;i>=x;--i)
using namespace std;
typedef long long ll;
int n,m;
const int inf=0x3f3f3f3f;
const int maxn=4e5+10;
ll x[maxn],y[maxn],A1,B1,C1,M1,A2,B2,C2,M2;
vector<ll >ve;
ll sz[maxn<<3],lazy[maxn<<3];
void add(int o,int l,int r,ll f){
    sz[o]+=(ve[r+1]-ve[l])*f;
    lazy[o]+=f;
}
void pushdown(int o,int l,int r){
    if(!lazy[o]||l==r)return;
    int mid=(l+r)>>1;
    add(o<<1,l,mid,lazy[o]);
    add(o<<1|1,mid+1,r,lazy[o]);
    lazy[o]=0;
}
void update(int o,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){
        add(o,l,r,1);
        return;
    }
    int mid=(l+r)>>1;
    pushdown(o,l,r);
    if(ql<=mid)update(o<<1,l,mid,ql,qr);
    if(mid<qr)update(o<<1|1,mid+1,r,ql,qr);
    sz[o]=sz[o<<1]+sz[o<<1|1];
}

ll query(int o,int l,int r,int num){
    if(l==r){
        ll tot=sz[o]/(ve[l+1]-ve[l]);
        return ve[l]+(num-1)/tot;
    }
    pushdown(o,l,r);
    int mid=(l+r)>>1;
    if(sz[o<<1]>=num)return query(o<<1,l,mid,num);
    return query(o<<1|1,mid+1,r,num-sz[o<<1]);
}


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);
       rep(i,3,n){
        x[i]=(A1*x[i-1]+B1*x[i-2]+C1)%M1;
        y[i]=(A2*y[i-1]+B2*y[i-2]+C2)%M2;
    }
    
    rep(i,1,n){
        x[i]++,y[i]++;
        if(x[i]>y[i]) swap(x[i],y[i]);
        ve.push_back(x[i]); ve.push_back(y[i]+1);
    }
    sort(ve.begin(),ve.end());
    ve.erase(unique(ve.begin(),ve.end()),ve.end());
    int cnt=ve.size();
    rep(i,1,n){
        
          x[i]=lower_bound(ve.begin(),ve.end(),x[i])-ve.begin();
        y[i]=lower_bound(ve.begin(),ve.end(),y[i]+1)-ve.begin();
        update(1,0,cnt,x[i],y[i]-1);
        printf("%lld\n",query(1,0,cnt,(sz[1]+1)/2));
    }
}

猜你喜欢

转载自www.cnblogs.com/mountaink/p/11327719.html