• Find the median(线段树离散化+区间更新)


    题目链接:https://ac.nowcoder.com/acm/contest/887/E

    链接:https://ac.nowcoder.com/acm/contest/887/E
    来源:牛客网

    Find the median
    时间限制:C/C++ 3秒,其他语言6秒
    空间限制:C/C++ 131072K,其他语言262144K
    64bit IO Format: %lld

    题目描述

    Let median of some array be the number which would stand in the middle of this array if it was sorted beforehand. If the array has even length let median be smallest of of two middle elements. For example, median of the array [10,3,2,3,2] is 3 (i.e. [2,2,3‾,3,10][2,2,underline{3},3,10][2,2,3,3,10]). Median of the array [1,5,8,1] is 1 (i.e. [1,1‾,5,8][1,underline{1},5,8][1,1,5,8]).

    At first, you're given an empty sequence. There are N operations. The i-th operation contains two integers LiL_iLi and RiR_iRi. This means that adding Ri−Li+1R_i-L_i+1RiLi+1 integers Li,Li+1,...,RiL_i, L_i+1, ... , R_iLi,Li+1,...,Ri into the sequence. After each operation, you need to find the median of the sequence.

    输入描述:

    The first line of the input contains an integer N (1≤N≤400000)N (1 leq N leq 400000)N (1N400000) as described above.

    The next two lines each contains six integers in the following format, respectively:

    - X1 X2 A1 B1 C1 M1X_1 X_2 A_1 B_1 C_1 M_1X1 X2 A1 B1 C1 M1
    - Y1 Y2 A2 B2 C2 M2Y_1 Y_2 A_2 B_2 C_2 M_2Y1 Y2 A2 B2 C2 M2

    These values are used to generate Li,RiL_i, R_iLi,Ri as follows:

    We define:
    - Xi=(A1×Xi−1+B1×Xi−2+C1) module M1X_i = (A_1 imes X_{i-1} + B_1 imes X_{i-2} + C_1) module M_1Xi=(A1×Xi1+B1×Xi2+C1) module M1, for i=3 to Ni = 3 to Ni=3 to N
    - Yi=(A2×Yi−1+B2×Yi−2+C2) module M2Y_i = (A_2 imes Y_{i-1} + B_2 imes Y_{i-2} + C_2) module M_2Yi=(A2×Yi1+B2×Yi2+C2) module M2, for i=3 to Ni = 3 to Ni=3 to NWe also define:-



    Li=min(Xi,Yi)+1L_i = min(X_i, Y_i) + 1Li=min(Xi,Yi)+1, for i=1 to Ni = 1 to Ni=1 to N.-
    Ri=max(Xi,Yi)+1R_i = max(X_i, Y_i) + 1Ri=max(Xi,Yi)+1, for i=1 to Ni = 1 to Ni=1 to N.Limits:


    1≤N≤4000001 leq N leq 4000001N400000
    0≤A1<M10 leq A_1 < M_10A1<M1
    0≤A2<M20 leq A_2 < M_20A2<M2
    0≤B1<M10 leq B_1 < M_10B1<M1
    0≤B2<M20 leq B_2 < M_20B2<M2
    0≤C1<M10 leq C_1 < M_10C1<M1
    0≤C2<M20 leq C_2 < M_20C2<M2
    0≤X1<M10 leq X_1 < M_10X1<M1
    0≤X2<M10 leq X_2 < M_10X2<M1
    0≤Y1<M20 leq Y_1 < M_20Y1<M2
    0≤Y2<M20 leq Y_2 < M_20Y2<M2
    1≤M1≤1091 leq M_1 leq 10^91M1109
    1≤M2≤1091 leq M_2 leq 10^91M2109

    输出描述:

    You should output 
    lines. Each line contains an integer means the median.
    示例1

    输入

    复制
    5
    3 1 4 1 5 9
    2 7 1 8 2 9
    

    输出

    复制
    3
    4
    5
    4
    5
    

    说明

    L = [3, 2 ,4, 1, 7]

    R = [4, 8, 8, 3, 9]
    题目大意:根据题意,可以得到一个长度为N 的L和R区间的数组,每次要加入集合的数是L[i]-R[i]之间所有的数,问你每次加入之后的中位数是什么,输出这个数
    思路:首先离散化所有L和R 但是这里进行离散的不是R[i] 而是R[i]+1 十分具体的原因我也不知道,但是这样做了之后要求区间时,只需要R[i]-L[i]了,不需要R[i]-L[i]+1
    看代码:
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef long long LL;
    const int maxn=400000+5;
    LL x[maxn],y[maxn],l[maxn],r[maxn];
    LL lazy[maxn<<3],sz[maxn<<3];
    vector<LL>ve;
    int cnt;
    void deal(int rt,int l,int r,LL f)
    {
        sz[rt]+=(ve[r+1]-ve[l])*f;lazy[rt]+=f;//注意这里要r+1
    }
    void Update(int l,int r,int rt,int L,int R)
    {
    //    cout<<"l:"<<l<<" r:"<<r<<endl;
        if(L<=l&&r<=R)
        {
            deal(rt,l,r,1);
            return ;
        }
        int mid=(l+r)>>1;
        if(lazy[rt])
        {
            deal(rt<<1,l,mid,lazy[rt]);
            deal(rt<<1|1,mid+1,r,lazy[rt]);
            lazy[rt]=0;
        }
        if(L<=mid) Update(l,mid,rt<<1,L,R);
        if(R>mid) Update(mid+1,r,rt<<1|1,L,R);
        sz[rt]=sz[rt<<1]+sz[rt<<1|1];
    }
    LL Query(int l,int r,int rt,LL x)
    {
    //    cout<<"ql:"<<l<<" qr:"<<r<<" x:"<<x<<endl;
        if(l==r)
        {
            int ti=sz[rt]/(ve[l+1]-ve[l]);//区间里每个数有多少个
            return ve[l]+(x-1)/ti;//(x-1)代表去掉本身 影响
        }
        int mid=(l+r)>>1;
        if(lazy[rt])
        {
            deal(rt<<1,l,mid,lazy[rt]);
            deal(rt<<1|1,mid+1,r,lazy[rt]);
            lazy[rt]=0;
        }
        if(sz[rt<<1]>=x) return Query(l,mid,rt<<1,x);//证明在左区间
        else return Query(mid+1,r,rt<<1|1,x-sz[rt<<1]);
    }
    int main()
    {
        int N;scanf("%d",&N);
        LL A1,B1,C1,M1;
        scanf("%lld%lld%lld%lld%lld%lld",&x[1],&x[2],&A1,&B1,&C1,&M1);
        LL A2,B2,C2,M2;
        scanf("%lld%lld%lld%lld%lld%lld",&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;
            ve.push_back(l[i]);ve.push_back(r[i]+1);//注意这里加入的是R[i]+1
        }
        sort(ve.begin(),ve.end());
        ve.erase(unique(ve.begin(),ve.end()),ve.end());//排序去重
        LL sum=0;int cnt=ve.size();
        for(int i=1;i<=N;i++)
        {
            sum+=r[i]-l[i]+1;
            int L=lower_bound(ve.begin(),ve.end(),l[i])-ve.begin();
            int R=lower_bound(ve.begin(),ve.end(),r[i]+1)-ve.begin();
            Update(0,cnt-1,1,L,R-1);//注意这里-1
            printf("%lld
    ",Query(0,cnt-1,1,(sum+1)/2));
        }
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    数组
    Fiddler抓手机APP包
    APP测试注意点-安装卸载与运行
    【转】查看iOS崩溃日志
    Monkey 命令
    python del 函数
    探索性测试方法
    解决5037端口占用的方法
    App测试Android的闪退总结
    Jenkins邮件配置
  • 原文地址:https://www.cnblogs.com/caijiaming/p/11348761.html
Copyright © 2020-2023  润新知