• [BZOJ2653]middle 主席树+二分


    2653: middle

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 2042  Solved: 1123
    [Submit][Status][Discuss]

    Description

    一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。给你一个
    长度为n的序列s。回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
    其中a<b<c<d。位置也从0开始标号。我会使用一些方式强制你在线。

    Input

    第一行序列长度n。接下来n行按顺序给出a中的数。
    接下来一行Q。然后Q行每行a,b,c,d,我们令上个询问的答案是
    x(如果这是第一个询问则x=0)。
    令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
    将q从小到大排序之后,令真正的
    要询问的a=q[0],b=q[1],c=q[2],d=q[3]。  
    输入保证满足条件。
    第一行所谓“排过序”指的是从大到小排序!
     

    Output

    Q行依次给出询问的答案。

    Sample Input

    5
    170337785
    271451044
    22430280
    969056313
    206452321
    3
    3 1 0 2
    2 3 1 4
    3 1 4 0

    271451044
    271451044
    969056313

    Sample Output

     

    HINT

      0:n,Q<=100

    1,...,5:n<=2000

    0,...,19:n<=20000,Q<=25000


    Source

    我们二分中位数,对于大于mid的数赋值为1,小于mid的数为-1。若最大的区间和大于0则可行。

    考虑建一颗主席树(维护权值线段树),root[i]为中位数为i时的前缀树。

    二分查询即可。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<algorithm>
     7 #define maxn 20005
     8 #define ls(i) t[i].s[0]
     9 #define rs(i) t[i].s[1]
    10 using namespace std;
    11 int read() {
    12     int x=0,f=1;char ch=getchar();
    13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    15     return x*f;
    16 }
    17 struct tmp {
    18     int v,id;
    19     bool operator <(const tmp tt) const {return v<tt.v;}
    20 }a[maxn];
    21 struct data {
    22     int lm,rm,sum,s[2];
    23 }t[maxn*20];
    24 int n,q,sz;
    25 int root[maxn];
    26 void pushup(int x) {
    27     t[x].lm=max(t[ls(x)].lm,t[ls(x)].sum+t[rs(x)].lm);
    28     t[x].rm=max(t[rs(x)].rm,t[rs(x)].sum+t[ls(x)].rm);
    29     t[x].sum=t[rs(x)].sum+t[ls(x)].sum;
    30 }
    31 void build(int &rt,int l,int r) {
    32     rt=++sz;
    33     if(l==r) {t[rt].sum=t[rt].lm=t[rt].rm=1;return;}
    34     int mid=l+r>>1;
    35     build(ls(rt),l,mid);build(rs(rt),mid+1,r);
    36     pushup(rt);
    37     
    38 }
    39 void update(int p,int &rt,int l,int r,int x) {
    40     rt=++sz;
    41     t[rt]=t[p];
    42     if(l==r) {t[rt].sum=-1;t[rt].lm=t[rt].rm=0;return;}
    43     int mid=l+r>>1;
    44     if(x<=mid) update(ls(p),ls(rt),l,mid,x);
    45     else update(rs(p),rs(rt),mid+1,r,x);
    46     pushup(rt);
    47 }
    48 int qs(int rt,int l,int r,int x,int y) {
    49     if(x>y) return 0;
    50     if(l>=x&&r<=y) return t[rt].sum;
    51     int mid=l+r>>1,ans=0;
    52     if(x<=mid) ans+=qs(ls(rt),l,mid,x,y);
    53     if(y>mid) ans+=qs(rs(rt),mid+1,r,x,y);
    54     return ans;
    55 }
    56 int ql(int rt,int l,int r,int x,int y) {
    57     if(x>y) return 0;
    58     if(l>=x&&r<=y) return t[rt].lm;
    59     int mid=l+r>>1,ans=0;
    60     if(x<=mid) ans=max(ql(ls(rt),l,mid,x,y),ans);
    61     if(y>mid) ans=max(qs(ls(rt),l,mid,x,mid)+ql(rs(rt),mid+1,r,x,y),ans);
    62     return ans;
    63 }
    64 int qr(int rt,int l,int r,int x,int y) {
    65     if(x>y) return 0;
    66     if(l>=x&&r<=y) return t[rt].rm;
    67     int mid=l+r>>1,ans=0;
    68     if(x<=mid) ans=max(qs(rs(rt),mid+1,r,mid+1,y)+qr(ls(rt),l,mid,x,y),ans);
    69     if(y>mid) ans=max(qr(rs(rt),mid+1,r,x,y),ans);
    70     return ans;
    71 }
    72 bool check(int x,int q1,int q2,int q3,int q4) {
    73     int s=qs(root[x],0,n-1,q2,q3)+ql(root[x],0,n-1,q3+1,q4)+qr(root[x],0,n-1,q1,q2-1);
    74     return s>=0;
    75 }
    76 int main() {
    77     t[0].sum=t[0].lm=t[0].rm=0;
    78     n=read();
    79     for(int i=0;i<n;i++) a[i].v=read(),a[i].id=i;
    80     sort(a,a+n);
    81     build(root[0],0,n-1);
    82     for(int i=1;i<n;i++) update(root[i-1],root[i],0,n-1,a[i-1].id);
    83     int ans=0;
    84     q=read();
    85     for(int i=1;i<=q;i++) {
    86         int ask[5];
    87         for(int j=1;j<=4;j++) ask[j]=(read()+ans)%n;
    88         sort(ask+1,ask+5);
    89         int L=0,R=n-1;
    90         while(L<=R) {
    91             int mid=L+R>>1;
    92             if(check(mid,ask[1],ask[2],ask[3],ask[4])) L=mid+1;
    93             else R=mid-1;
    94         }
    95         ans=a[L-1].v;
    96         printf("%d
    ",ans);
    97     }
    98 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    分布式锁相关
    《并发编程的艺术》笔记
    JVM相关总结
    redisTemplate类学习及理解
    wondows 安装 OpenSSH
    centos系统下,mysql常用命令 vofill
    查看centos7服务器信息常用命令 vofill
    封装SQL2005数据库操作的Framework
    C# 获取到当前处于活跃状态的Excel对象(即已经打开的)c#获取打开的excel
    QML Qt Quick Study Note No.2
  • 原文地址:https://www.cnblogs.com/wls001/p/8179252.html
Copyright © 2020-2023  润新知