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

    题目链接:洛谷

    题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值。(强制在线)

    这里的中位数定义为,对于一个长度为$n$的序列排序之后为$a_0,a_1,ldots,a_{n-1}$,则$a_{lfloorfrac{n}{2} floor}$为这个序列的中位数。

    数据范围:$1leq nleq 20000$,$1leq qleq 25000$,$1leq aleq bleq cleq dleq n$


    这道题才是真正的主席树!

    首先我们考虑离散化,然后二分答案,判断这些区间的中位数是否有可能$geq mid$,那怎么判断呢?

    我们发现,如果把这个序列的所有$geq mid$的数改为1,$<mid$的数改为$-1$,则上述条件等价于这个新的数列之和非负。(这是一个非常神仙的套路)

    所以我们对于所有的数$a_i$,预处理出这个1/-1的序列,但是这样空间会爆炸。

    我们发现这些序列中,$a_{i-1}$和$a_i$的序列之间仅有一位不同。

    于是主席树闪亮登场。

    然后判断一下左端点在$[a,b]$,右端点在$[c,d]$的最大子段和,判断一下是否$geq 0$。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define Rint register int
     4 using namespace std;
     5 const int N = 20003;
     6 int n, Q, q[4], lans, a[N], id[N], root[N], ls[N << 5], rs[N << 5], cnt;
     7 struct Node {
     8     int sum, lmax, rmax;
     9     inline Node(int s = 0, int l = 0, int r = 0): sum(s), lmax(l), rmax(r){}
    10     inline Node operator + (const Node &o) const {
    11         return Node(sum + o.sum, max(lmax, sum + o.lmax), max(o.rmax, o.sum + rmax));
    12     }
    13 } seg[N << 5];
    14 inline void pushup(int x){
    15     seg[x] = seg[ls[x]] + seg[rs[x]];
    16 }
    17 inline void build(int &x, int L, int R){
    18     x = ++ cnt;
    19     if(L == R){
    20         seg[x] = Node(1, 1, 1);
    21         return;
    22     }
    23     int mid = L + R >> 1;
    24     build(ls[x], L, mid);
    25     build(rs[x], mid + 1, R);
    26     pushup(x);
    27 }
    28 inline void change(int &nx, int ox, int L, int R, int pos){
    29     nx = ++ cnt;
    30     ls[nx] = ls[ox]; rs[nx] = rs[ox];
    31     if(L == R){
    32         seg[nx] = Node(-1, -1, -1);
    33         return;
    34     }
    35     int mid = L + R >> 1;
    36     if(pos <= mid) change(ls[nx], ls[ox], L, mid, pos);
    37     else change(rs[nx], rs[ox], mid + 1, R, pos);
    38     pushup(nx);
    39 }
    40 inline Node query(int x, int L, int R, int l, int r){
    41     if(!x || l > r) return Node();
    42     if(l <= L && R <= r) return seg[x];
    43     int mid = L + R >> 1;
    44     if(r <= mid) return query(ls[x], L, mid, l, r);
    45     else if(mid < l) return query(rs[x], mid + 1, R, l, r);
    46     else return query(ls[x], L, mid, l, r) + query(rs[x], mid + 1, R, l, r);
    47 }
    48 inline int solve(int a, int b, int c, int d){
    49     int l = 1, r = n, mid, tmp;
    50     while(l <= r){
    51         mid = l + r >> 1;
    52         tmp = query(root[mid], 1, n, a, b).rmax + query(root[mid], 1, n, b + 1, c - 1).sum + query(root[mid], 1, n, c, d).lmax;
    53         if(tmp >= 0) l = mid + 1;
    54         else r = mid - 1;
    55     }
    56     return id[r];
    57 }
    58 int main(){
    59     scanf("%d", &n);
    60     for(Rint i = 1;i <= n;i ++){
    61         scanf("%d", a + i); id[i] = i; 
    62     }
    63     sort(id + 1, id + n + 1, [](int x, int y) -> bool {return a[x] < a[y];});
    64     build(root[1], 1, n);
    65     for(Rint i = 1;i < n;i ++)
    66         change(root[i + 1], root[i], 1, n, id[i]);
    67     scanf("%d", &Q);
    68     while(Q --){
    69         for(Rint i = 0;i < 4;i ++){
    70             scanf("%d", q + i);
    71             q[i] = (q[i] + lans) % n + 1;
    72         }
    73         sort(q, q + 4);
    74         printf("%d
    ", lans = a[solve(q[0], q[1], q[2], q[3])]);
    75     }
    76 }
    View Code
  • 相关阅读:
    Jquery字符串,数组(拷贝、删选、合并等),each循环,阻止冒泡,ajax出错,$.grep筛选,$.param序列化,$.when
    Jquery cookie操作示例,写入cookie,读取cookie,删除cookie
    执行Sqlserver中waitfor delay延时操作或waitfor time定时操作
    JS里try...catch...finally详解,以及console日志调试(console.log、console.info等)
    19.Remove Nth Node From End of List---双指针
    18.4Sum
    16.3Sum Closest
    45.Jump Game II---贪心---2018大疆笔试题
    55.Jump Game---dp
    SQL相关
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/10630747.html
Copyright © 2011-2022 走看看