여름 학교 캠프 (일곱 번째) 중앙값 (범위 세그먼트 트리 + 이산 점)을 찾기 -E 오프 이상 2019 소

항목 링크 : HTTPS : //ac.nowcoder.com/acm/contest/887/E

문제의 의미 부여 L [i]를, R [i]를, L의 각 추가 [I] ... R [i]는, 현재 계산 된 중앙값.

아이디어 : 범위의 수 1E9에 첨가하기 때문에, 제 이산 사용할 생각 여기 범위를 표시하는 점이다.

 

 

게다가 바로 주요 목적의 부분은 프로세스를 최적화하는 것입니다, 그 전면에 통합 마지막 요소의 범위를 이해하는 순간을 시뮬레이션 할 수 있습니다.

그런 다음 각 노드에 포함 된 요소의 수와 트리 라인 플러스 게으른 마크 LAZ으로 표시 수, 각 시간을 유지하는 쿼리 왼쪽 서브 트리의 왼쪽 서브 트리 충분한 질의 요소의 수, 또는 오른쪽 하위 트리에있는 경우 쿼리.

코드를 참조하십시오 :

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

typedef long long LL;
const int maxn=4e5+5;

struct node{
    int l,r,laz;
    LL sz;
}tr[maxn<<3];

int n;
LL X[maxn],Y[maxn],A1,A2,B1,B2,C1,C2,M1,M2;
vector<int> vc;

void build(int v,int l,int r){
    tr[v].l=l,tr[v].r=r;
    if(l==r){
        return;
    }
    int mid=(l+r)>>1;
    build(v<<1,l,mid);
    build(v<<1|1,mid+1,r);
}

void pushdown(int v){
    tr[v<<1].sz+=(vc[tr[v<<1].r+1]-vc[tr[v<<1].l])*tr[v].laz;
    tr[v<<1].laz+=tr[v].laz;
    tr[v<<1|1].sz+=(vc[tr[v<<1|1].r+1]-vc[tr[v<<1|1].l])*tr[v].laz;
    tr[v<<1|1].laz+=tr[v].laz;
    tr[v].laz=0;
}

void update(int v,int l,int r){
    if(l<=tr[v].l&&r>=tr[v].r){
        tr[v].sz+=(vc[tr[v].r+1]-vc[tr[v].l]);
        tr[v].laz+=1;
        return;
    }
    if(tr[v].laz) pushdown(v);
    int mid=(tr[v].l+tr[v].r)>>1;
    if(l<=mid) update(v<<1,l,r);
    if(r>mid) update(v<<1|1,l,r);
    tr[v].sz=tr[v<<1].sz+tr[v<<1|1].sz;
}

int query(int v,LL k){
    if(tr[v].l==tr[v].r){
        int tmp=tr[v].sz/(vc[tr[v].l+1]-vc[tr[v].l]);
        return vc[tr[v].l]+(k-1)/tmp;
    }
    if(tr[v].laz) pushdown(v);
    if(k<=tr[v<<1].sz) return query(v<<1,k);
    else return query(v<<1|1,k-tr[v<<1].sz);
}

int main(){
    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);
    for(int i=3;i<=n;++i){
        X[i]=(A1*X[i-1]%M1+B1*X[i-2]%M1+C1)%M1;
        Y[i]=(A2*Y[i-1]%M2+B2*Y[i-2]%M2+C2)%M2;
    }
    for(int i=1;i<=n;++i){
        ++X[i],++Y[i];
        if(X[i]>Y[i]) swap(X[i],Y[i]);
        vc.push_back(X[i]),vc.push_back(Y[i]+1);
    }
    sort(vc.begin(),vc.end());
    vc.erase(unique(vc.begin(),vc.end()),vc.end());
    LL sum=0;
    int cnt=vc.size();
    build(1,0,cnt-1);
    for(int i=1;i<=n;++i){
        sum+=Y[i]-X[i]+1;
        int x,y;
        x=lower_bound(vc.begin(),vc.end(),X[i])-vc.begin();
        y=lower_bound(vc.begin(),vc.end(),Y[i]+1)-vc.begin();
        update(1,x,y-1);
        printf("%d\n",query(1,(sum+1)>>1));
    }
    return 0;
}

 

추천

출처www.cnblogs.com/FrankChen831X/p/11349154.html