• 2653: middle


    2653: middle

    链接

    分析:

      二分答案+主席树。

      对于中位数的经典做法,就是二分一个数,将小于的变成-1,大于等于的变成+1,那么如果sum>=0(因为+1包括等于),L=mid+1,否则R=mid-1。

      那么考虑二分一个中位数(当然只二分出现过的数即可),然后向上面一样判断。

      因为二分的数字只有n个,可以建立n颗只包含-1和+1的权值线段树,发现第i小的权值线段树与第i+1小的权值线段树只有一个位置不同,所以可以类似可持久化的思路,每次只去建立一条链。

      查询的区间有很多个,不能挨个查询它们的和,由于查询最大值,所以可以再在线段树上维护左端最大子段和,右端最大子段和。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    #define pa pair<int,int>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 20005;
    struct Node{
        int sum, Lmx, Rmx; 
    }T[N * 20];
    int ls[N * 20], rs[N * 20], Root[N], Index, n;
    pa A[N];
    
    Node operator + (const Node &A,const Node &B) {
        Node res;
        res.sum = A.sum + B.sum;
        res.Lmx = max(A.Lmx, A.sum + B.Lmx);
        res.Rmx = max(B.Rmx, A.Rmx + B.sum);
        return res;
    }
    void build(int l,int r,int &rt) {
        rt = ++Index;
        if (l == r) {
            T[rt].sum = T[rt].Lmx = T[rt].Rmx = 1; return ;
        }
        int mid = (l + r) >> 1;
        build(l, mid, ls[rt]); build(mid + 1, r, rs[rt]);
        T[rt] = T[ls[rt]] + T[rs[rt]];
    }
    void update(int l,int r,int &rt,int pre,int p) {
        if (!rt) rt = ++Index;
        if (l == r) {
            T[rt].sum = T[rt].Lmx = T[rt].Rmx = -1; return ;
        }
        int mid = (l + r) >> 1;
        if (p <= mid) {
            rs[rt] = rs[pre];
            update(l, mid, ls[rt], ls[pre], p);
        } else {
            ls[rt] = ls[pre];
            update(mid + 1, r, rs[rt], rs[pre], p);
        }
        T[rt] = T[ls[rt]] + T[rs[rt]];
    }
    Node query(int l,int r,int rt,int L,int R) {
        if (L <= l && r <= R) return T[rt];
        int mid = (l + r) >> 1;
        if (R <= mid) return query(l, mid, ls[rt], L, R);
        else if (L > mid) return query(mid + 1, r, rs[rt], L, R);
        else return query(l, mid, ls[rt], L, R) + query(mid + 1, r, rs[rt], L, R);
    }
    bool check(int x,int l1,int r1,int l2,int r2) {
        Node a, b, c; b.sum = 0;
        if (l2 > r1 + 1) b = query(1, n, Root[x], r1 + 1, l2 - 1);
        a = query(1, n, Root[x], l1, r1);
        c = query(1, n, Root[x], l2, r2);
        return (a.Rmx + b.sum + c.Lmx) >= 0;
    }
    int main() {
        n = read();
        for (int i = 1; i <= n; ++i) {
            A[i].first = read(), A[i].second = i;
        }
        sort(A + 1, A + n + 1);
        build(1, n, Root[1]);
        for (int i = 2; i <= n; ++i) 
            update(1, n, Root[i], Root[i - 1], A[i - 1].second);
        int c[5], m = read(), ans = 0, pos;
        while (m --) {
            for (int i = 0; i < 4; ++i) c[i] = (read() + ans) % n + 1;
            sort(c, c + 4);
            int l = 1, r = n;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (check(mid, c[0], c[1], c[2], c[3])) pos = mid, l = mid + 1;
                else r = mid - 1;
            }
            ans = A[pos].first;
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    input 标签取消readOnly属性
    python selenium 跑脚本的时候按钮无法点击的解决办法
    Python Selenium 调用IE浏览器失败Unexpected error launching Internet Explorer解决方法
    转载--Python random模块(获取随机数)常用方法和使用例子
    转载--python selenium实现文件、图片上传
    ieDriver启动IE浏览器显示This is the initial start page for the WebDriver server的解决办法
    自动化测试用例设计学习心得总结
    关于selene安装插件ide不能识别插件的问题解决办法
    cmd 启动mysql
    最大子序列
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10295613.html
Copyright © 2020-2023  润新知