牛客 Find the median 权值线段树 离散化

  题意: 一开始为空序列  每次加入 L R  之间的数字(包括L,R )  问中位数为多少  

很显然是一个权值线段树  但是R的范围有1e9   比赛的时候没想到离散化QAQ(主要是被那个解密过程给恶心到了  woc明明没有强制在线 还解个锤子迷)

要将两个闭区间改为左闭右开  ( 有点像扫描线)  所以r[i]+1即可

然后就是线段树每个点代表的是一个区间

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
typedef pair<int,int>pii;
//////////////////////////////////
const int N=800000+10;
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1

ll t[N<<2],len[N<<2],b[N<<2],col[N<<2];

void up(int pos)
{
    t[pos]=t[pos<<1]+t[pos<<1|1];
}

void build(int l,int r,int pos)
{
    if(l==r){len[pos]=b[l+1]-b[l];return ;}
    int m=(l+r)>>1;
    build(lson);build(rson);
    len[pos]=len[pos<<1]+len[pos<<1|1];
}

void down(int pos)
{
    if(!col[pos])return ;
    col[pos<<1]+=col[pos];
    col[pos<<1|1]+=col[pos];
    t[pos<<1]+=col[pos]*len[pos<<1];
    t[pos<<1|1]+=col[pos]*len[pos<<1|1];
    col[pos]=0;
}

void upsum(int L,int R,int l,int r,int pos)
{
    if(L<=l&&r<=R)
    {
        col[pos]++;t[pos]+=len[pos];
        return ;
    }
    down(pos);int m=l+r>>1;
    if(L<=m)upsum(L,R,lson);
    if(R>m)upsum(L,R,rson);
    up(pos);
}

ll qsum(ll k,int l,int r,int pos)
{
    if(l==r)
    {
        ll temp=t[pos]/len[pos];
        return  b[l]+1ll*(k-1)/temp;
    }
    int m=(l+r)>>1;down(pos);

    if(t[pos<<1]>=k)return qsum(k,lson);
    else return qsum(k-t[pos<<1],rson);
}
ll n,m,x[N],y[N],a1,b1,c1,m1,a2,b2,c2,m2,l[N],r[N],cnt;

int main()
{
    cin>>n;
    cin>>x[1]>>x[2]>>a1>>b1>>c1>>m1;
    cin>>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)
    {
        l[i]=min(x[i],y[i])+1;
        r[i]=max(x[i],y[i])+1;
        r[i]++;
        b[++cnt]=l[i];b[++cnt]=r[i];
    }
    sort(b+1,b+1+cnt);
    m=unique(b+1,b+1+cnt)-b-1;

    build(1,m-1,1);

    ll sum=0;
    rep(i,1,n)
    {
        int L=lower_bound(b+1,b+1+cnt,l[i])-b;
        int R=lower_bound(b+1,b+1+cnt,r[i])-b;
        sum+=r[i]-l[i];
        upsum(L,R-1,1,m-1,1);
        printf("%lld\n",qsum((sum+1)/2,1,m-1,1));
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/bxd123/p/11326943.html
今日推荐