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 \times X_{i-1} + B_1 \times 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 \times Y_{i-1} + B_2 \times 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\n",Query(0,cnt-1,1,(sum+1)/2));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caijiaming/p/11348761.html
今日推荐