zoukankan      html  css  js  c++  java
  • [国家集训队]middle 题解

    题面传送门

    这道题我们首先会想到处理中位数的常见方法:

    二分枚举答案ans,将大于ans的数变为1,小于的则变成-1;如果这个区间的和大于1,则说明中位数比枚举的答案要大,否则要小;

    但是这道题的区间并不确定,难道我们要n*n枚举?肯定不行;

    观察性质,我们发现,对于区间[b,c],我们肯定要选择,那么先把这个区间的和加入到答案里;

    因为题中说选择尽量大的中位数,根据二分时的性质,区间和越大,中位数越大;所以我们所选择的区间的和要最大;

    也就是说,我们还要选取rmax[a,b]和lmax[c,d];

    综上所述,对于每次二分的判定,如果rmax[a,b]+lmax[c,d]+sum(b,c)>=0,则说明中位数比现在枚举的答案大,然后更改二分条件L=mid+1;

    我们可以对于每次二分的答案将区间改成01序列,利用线段树可以做到nlogn;

    可是这样空间复杂度原地爆炸,于是想到了我们的好朋友:主席树;

    发现:如果二分的答案ans变为ans+1,那么ans+1所对应的线段树上相对于ans的线段树只有等于ans+1的点的权值有所变动,显然每次多需要建的树节点均摊下来只有(logn);

    于是开心的用$nlog ^{2}n$的时间复杂度AC掉了这道题;

    #include <bits/stdc++.h>
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    using namespace std;
    int aa[20010],lisan;
    int in[10],root[20010];
    class node2{
        public:
        int x,id;
    }query[200010];
    bool cmp(node2 x,node2 y){
        return x.x<y.x;
    }
    class node{
        public:
        int lson,rson;
        int sum,lmax,rmax;
        #define mid (l+r)/2
    }tree[2000010];
    int tot;
    void updata(int k){
        tree[k].sum=tree[tree[k].lson].sum+tree[tree[k].rson].sum;
        tree[k].lmax=max(tree[tree[k].lson].lmax,tree[tree[k].rson].lmax+tree[tree[k].lson].sum);
        tree[k].rmax=max(tree[tree[k].rson].rmax,tree[tree[k].lson].rmax+tree[tree[k].rson].sum);
    }
    int build(int l,int r){
        int root=++tot;
        if(l==r){
            tree[root].sum=tree[root].lmax=tree[root].rmax=1;
            return root;
        }
        tree[root].lson=build(l,mid);
        tree[root].rson=build(mid+1,r);
        updata(root); return root;
    }
    void add(int &now,int pre,int l,int r,int goal,int value){
        now=++tot;
        tree[now]=tree[pre];
        if(l==r){
            tree[now].lmax=tree[now].rmax=tree[now].sum=value;
            return;
        }
        if(goal<=mid){
            add(tree[now].lson,tree[pre].lson,l,mid,goal,value);
        }
        else{
            add(tree[now].rson,tree[pre].rson,mid+1,r,goal,value);
        }
        updata(now);
    }
    int querysum(int now,int l,int r,int x,int y){
        if(x>r||y<l) return 0;
        if(x<=l&&r<=y) return tree[now].sum;
        return (querysum(tree[now].lson,l,mid,x,y)+querysum(tree[now].rson,mid+1,r,x,y));
    }
    int querylmax(int now,int l,int r,int x,int y){
        if(x>r||y<l) return -99999999;
        if(x<=l&&r<=y) return tree[now].lmax;
        return max(querylmax(tree[now].lson,l,mid,x,y),querylmax(tree[now].rson,mid+1,r,x,y)+querysum(tree[now].lson,l,mid,x,y));
    }
    int queryrmax(int now,int l,int r,int x,int y){
        if(x>r||y<l) return -99999999;
        if(x<=l&&r<=y) return tree[now].rmax;
        int tmp1=queryrmax(tree[now].rson,mid+1,r,x,y),tmp2=queryrmax(tree[now].lson,l,mid,x,y)+querysum(tree[now].rson,mid+1,r,x,y);
        return max(tmp1,tmp2);
    }
    int n; 
    bool check(int now,int a,int b,int c,int d){
        int sum=0;
        if(b+1<=c-1) sum+=querysum(root[now],1,n,b+1,c-1);
        sum+=queryrmax(root[now],1,n,a,b);
        sum+=querylmax(root[now],1,n,c,d);
        if(sum>=0) return 1;
        else return 0;
    }
    int main()
    {
        scanf("%d",&n);
        inc(i,1,n){
            scanf("%d",&query[i].x);
            query[i].id=i;
        }
        sort(query+1,query+1+n,cmp);
        root[1]=build(1,n);
        inc(i,2,n+1){
            add(root[i],root[i-1],1,n,query[i-1].id,-1);
        }
        int q; scanf("%d",&q);
        int ans=0;
        inc(i,1,q){
            scanf("%d%d%d%d",&in[0],&in[1],&in[2],&in[3]);
            in[0]=(in[0]+ans)%n; in[1]=(in[1]+ans)%n; in[2]=(in[2]+ans)%n; in[3]=(in[3]+ans)%n;
            sort(in,in+4);
            int L=1,R=n;
            while(L<=R){
                int midd=(L+R)/2;
                if(check(midd,in[0]+1,in[1]+1,in[2]+1,in[3]+1)){
                    L=midd+1; ans=midd;
                }
                else{
                    R=midd-1;
                }
            }
            ans=query[ans].x;
            printf("%d
    ",ans);
        }
    }
    /*
    5
    170337785
    271451044
    22430280
    969056313
    206452321
    3
    3 1 0 2
    2 3 1 4
    3 1 4 0
    */
  • 相关阅读:
    fn project 试用之后的几个问题的解答
    fn project 扩展
    fn project 生产环境使用
    fn project 对象模型
    fn project AWS Lambda 格式 functions
    fn project 打包Function
    fn project Function files 说明
    fn project hot functions 说明
    fn project k8s 集成
    fn project 私有镜像发布
  • 原文地址:https://www.cnblogs.com/kamimxr/p/12108639.html
Copyright © 2011-2022 走看看