zoukankan      html  css  js  c++  java
  • [bzoj2653]middle

    来自FallDream的博客,未经允许,请勿转载,谢谢


    ditoly太强了 随便切  我被d飞了

    -------------------------------

    由n个数ai,每次询问,给定四个数a,b,c,d,求一个左端点在[a,b],右端点在[c,d]的子序列(原题这么写,但是实际上是子串),使得它的中位数最大。强制在线

    n<=20000 q<=25000

    题解:考虑二分一个答案,然后check一下是否能够取到。

    怎么check呢?假设要check一个数X,那么我们把大等于X的数字看成1,小于的看成-1,如果存在一个子序列的和大等于0,那么这个数字就是合法的。

    所以我们可以维护一棵线段树,直接把每一位看成1或者-1,维护前缀和数组的最大最小值,然后数字从小到大把线段树可持久化一下,每次一个数字从1变成-1就是把一段区间-2,这个我们通过标记永久化实现。

    复杂度$qlog^{2}n$

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define MN 20000
    #define pa pair<int,int>
    #define mp(x,y) make_pair(x,y)
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,m,last=0,num[10],a[MN+5],cnt=0,l[MN+5],rt[MN+5];
    pa p[MN+5];
    
    struct data{
        int mx,mn;
        data(int x=0):mx(x),mn(x){}
        data(int x,int y):mx(x),mn(y){}
        data operator*(const data&b){return data(max(mx,b.mx),min(mn,b.mn));} 
        data operator+(int y){return data(mx+y,mn+y);}
    };
    struct node{int l,r,val;data x;}T[MN*60+5];
    
    inline int mark(int x,int k)
    {
        int nx=++cnt;T[nx].l=T[x].l;T[nx].r=T[x].r;
        T[nx].x=T[x].x+k;T[nx].val=T[x].val+k;    
        return nx;
    }
    
    void pushdown(int x)
    {
        T[x].l=mark(T[x].l,T[x].val);
        T[x].r=mark(T[x].r,T[x].val);
        T[x].val=0;
    }
    
    int ins(int x,int l,int r,int ad,int lt=0,int rt=n)
    {
        if(l==lt&&rt==r){return mark(x,ad);}
        int nx=mark(x,0);pushdown(nx);
        int mid=lt+rt>>1;
        if(r<=mid) 
            T[nx].l=ins(T[nx].l,l,r,ad,lt,mid);
        else if(l>mid)
            T[nx].r=ins(T[nx].r,l,r,ad,mid+1,rt);
        else 
            T[nx].l=ins(T[nx].l,l,mid,ad,lt,mid),T[nx].r=ins(T[nx].r,mid+1,r,ad,mid+1,rt);
        T[nx].x=T[T[nx].l].x*T[T[nx].r].x;
        return nx;
    }
    
    int build(int l,int r)
    {
        int x=++cnt,mid=l+r>>1;
        if(l==r) {T[x].x=data(l);return x;}
        T[x].l=build(l,mid);T[x].r=build(mid+1,r);
        T[x].x=T[T[x].l].x*T[T[x].r].x;
        return x;
    }
    
    data query(int x,int l,int r,int lt=0,int rt=n)
    {
        if(l==lt&&rt==r) return T[x].x;
        int mid=lt+rt>>1;
        if(r<=mid) return query(T[x].l,l,r,lt,mid)+T[x].val;
        else if(l>mid) return query(T[x].r,l,r,mid+1,rt)+T[x].val;
        else return query(T[x].l,l,mid,lt,mid)*query(T[x].r,mid+1,r,mid+1,rt)+T[x].val;
    }
    
    int main()
    {    
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=n;i++) p[i]=mp(a[i],i);
        sort(p+1,p+n+1);rt[1]=build(0,n);
        for(int i=2;i<=n;i++)
            rt[i]=ins(rt[i-1],p[i-1].second,n,-2);
        m=read();
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=4;j++) num[j]=(read()+last)%n+1;
            sort(num+1,num+5);
            int a=num[1],b=num[2],c=num[3],d=num[4];
            int L=1,R=n,mid,ans=0;
            while(L<=R)
            {
                mid=L+R>>1;    
                if(query(rt[mid],c,d).mx-query(rt[mid],a-1,b-1).mn>=0) ans=mid,L=mid+1;
                else R=mid-1;
            }
            printf("%d
    ",last=p[ans].first);
        }
        return 0;
    }
  • 相关阅读:
    每一次要fix的pr
    docker && k8s
    beisen
    c++迭代器失效问题
    视频分析
    视频分析记录
    深信服实习生笔试题-20190315
    laravel接口设计
    tensorflow利用预训练模型进行目标检测(四):检测中的精度问题以及evaluation
    tensorflow利用预训练模型进行目标检测(三):将检测结果存入mysql数据库
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2653.html
Copyright © 2011-2022 走看看