• [国家集训队]middle


    [国家集训队]middle

    Description

    给你一个长度为n的序列s。 回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。 强制在线
     

    Solution

     考虑二分答案,把问题转化成可行性问题,然后发现b+1 - c-1 是一定必选的,另外两边要想最大就是维护一个连续最大子段和

    然后每次二分值改变,只会影响线段树上log个位置,于是考虑主席树

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read()
    {
        int f = 1 , x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch=='-') f=-1;
        } while(ch<'0'||ch>'9');
        do
        {
            x=(x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch>='0'&&ch<='9');
        return f*x;
    }
    
    const int MAXN = 20000 + 5;
    
    int n;
    
    struct NUM
    {
        int val;
        int pos;
        friend bool operator < (NUM a1,NUM a2)
        {
            return a1.val < a2.val;
        }
    }a[MAXN];
    
    struct P_Tree
    {
        int lc,rc;
        int lmax;
        int rmax;
        int sum;
    }tree[MAXN * 18];
    int cnt,root[MAXN];
    int q[4];
    
    inline void pushup(int rt)
    {
        tree[rt].sum = tree[tree[rt].lc].sum + tree[tree[rt].rc].sum;
        tree[rt].lmax = max(tree[tree[rt].lc].lmax,tree[tree[rt].rc].lmax+tree[tree[rt].lc].sum);
        tree[rt].rmax = max(tree[tree[rt].rc].rmax,tree[tree[rt].lc].rmax+tree[tree[rt].rc].sum);
    }
    
    inline void build(int &rt,int l,int r)
    {
        if(!rt) rt = ++cnt;
        if(l == r)
        {
            tree[rt].lmax = tree[rt].rmax = tree[rt].sum = 1;
            return;
        }
        int mid = (l + r) >> 1;
        build(tree[rt].lc,l,mid);
        build(tree[rt].rc,mid+1,r);
        pushup(rt);
    }
    
    inline void insert(int &rt,int rt1,int l,int r,int k)
    {
        if(!rt) rt = ++cnt;
        tree[rt] = tree[rt1];
        if(l == r)
        {
            tree[rt].sum = -1;
            tree[rt].lmax = -1;
            tree[rt].rmax = -1;
            return;
        }
        int mid = (l + r) >> 1;
        if(mid >= k) tree[rt].lc = 0,insert(tree[rt].lc,tree[rt1].lc,l,mid,k);
        else tree[rt].rc = 0,insert(tree[rt].rc,tree[rt1].rc,mid+1,r,k);
        pushup(rt);
    }
    
    inline int query3(int rt,int l,int r,int L,int R)
    {
        if(L<=l&&R>=r) return tree[rt].sum;
        if(L>r||l>R) return 0;
        int mid = (l + r) >> 1;
        return query3(tree[rt].lc,l,mid,L,R) + query3(tree[rt].rc,mid+1,r,L,R);
    }
    
    inline int query1(int rt,int l,int r,int L,int R)
    {
        if(L<=l&&R>=r) return tree[rt].rmax;
        //if(L>r||l>R) return 0;
        int mid = (l + r) >> 1;
        if(R <= mid) return query1(tree[rt].lc,l,mid,L,R);
        else if(L >= mid + 1) return query1(tree[rt].rc,mid+1,r,L,R); 
        return max(query1(tree[rt].rc,mid+1,r,mid+1,R),query3(tree[rt].rc,mid+1,r,mid+1,R) + query1(tree[rt].lc,l,mid,L,mid));
    }
    
    inline int query2(int rt,int l,int r,int L,int R)
    {
        if(L<=l&&R>=r) return tree[rt].lmax;
    //    if(L>r||l>R) return 0;
        int mid = (l + r) >> 1;
        if(R <= mid) return query2(tree[rt].lc,l,mid,L,R);
        else if(L >= mid + 1) return query2(tree[rt].rc,mid+1,r,L,R); 
        return max(query2(tree[rt].lc,l,mid,L,mid),query3(tree[rt].lc,l,mid,L,mid) + query2(tree[rt].rc,mid+1,r,mid+1,R));
    }
    
    inline bool check(int mid)
    {
        int res = 0;
        res = query1(root[mid],1,n,q[0],q[1]) + query2(root[mid],1,n,q[2],q[3]);
        if(q[2]-1 >= q[1] + 1) res += query3(root[mid],1,n,q[1]+1,q[2]-1);
        return res >= 0;
    }
    
    int main()
    {
        n = read();
        for(int i=1;i<=n;i++) a[i].val = read(),a[i].pos = i;
        sort(a+1,a+n+1);
        build(root[1],1,n);
        for(int i=2;i<=n+1;i++) insert(root[i],root[i-1],1,n,a[i-1].pos);
        int Q = read(),lastans = 0;
        while(Q--)
        {
            int A = read(),B = read(),C = read(),D = read();
            q[0] = (A + lastans) % n + 1,q[1] = (B + lastans) % n + 1,q[2] = (C + lastans) % n + 1,q[3] = (D + lastans) % n + 1;
            sort(q,q+4);
            int l = 1,r = n + 1,ans = 0;
            while(l <= r)
            {
                int mid = (l + r) >> 1;
                if(check(mid)) l = mid + 1,ans = mid;
                else r = mid - 1;
             } 
             lastans = a[ans].val;
             printf("%d
    ",lastans);
        }
    }
  • 相关阅读:
    rocketmq详解
    rocketmq的windows版客户端的启动步骤
    postman提交数组格式方式
    关于springmvc的包含list提交的格式
    数据库字段和实体类和map中对应类型
    怎么连接两个数据库和怎么停止上一个线程
    IDEA 创建类是自动添加注释和创建方法时快速添加注释
    centOs7 安装mysql8
    CentOS7安装Nginx及配置
    windows安装mysql8详解
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/13971438.html
Copyright © 2020-2023  润新知