• bzoj2653: middle


    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

    题解:

    这道题是基于这么个idea,如何在不求出一个数列a的中位数的情况下,判断数x是大于等于中位数

    我们可以考虑定义一个新数列b,满足b[i]= a[i]>=x?1:-1 ,如果b数列的总和大于等于0,则数x小于等于中位数,否则反之

    然后这道题我们可以二分一个数x,判断是否能成为中位数,我们可以将大于等于x的数看成1,小于的看成-1

    查询左端点在 [ a , b ] , 右端点在 [ c , d ] 的最大子段和,如果最大子段和大于等于0,说明x小于等于中位数,否则反之

    但现在x是变化的,我们显然不能每次暴力把某个数改成1或-1

    显然x只能是原序列的数

    将原序列的数离散化一下后,此时x的取值范围显然是1到n,我们发现当x变成x+1时,只有第x个数由+1变为-1

    而对于某个序列的最大子段和显然可以用线段树维护,而每次只会修改一个数

    我们就可以用可持久化线段树把历史上每个线段树都建出来,然后在第x个上进行查询

    总的时间复杂度为O( n log 2 n )

    code:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 char ch;
     8 bool ok;
     9 void read(int &x){
    10     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    11     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    12     if (ok) x=-x;
    13 }
    14 const int maxn=20005;
    15 const int maxnode=310000;
    16 const int inf=0x7f7f7f7f;
    17 int n,q,t[4],ans;
    18 struct Data{
    19     int v,id;
    20     void init(int i){read(v),id=i;}
    21 }list[maxn];
    22 bool cmp(const Data &a,const Data &b){return a.v<b.v;}
    23 struct Node{
    24     int lmax,rmax,maxv,sum;
    25     void init(int v){lmax=rmax=maxv=sum=v;}
    26 }t1,t2,t3;
    27 Node operator+(const Node &x,const Node &y){
    28     return (Node){max(x.lmax,x.sum+y.lmax),max(y.rmax,y.sum+x.rmax),max(x.rmax+y.lmax,max(x.maxv,y.maxv)),x.sum+y.sum};
    29 }
    30 struct seg{
    31     int tot,root[maxn],son[maxnode][2];
    32     Node node[maxnode];
    33     void build(int &k,int l,int r){
    34         k=++tot;
    35         if (l==r){node[k].init(1);return;}
    36         int m=(l+r)>>1;
    37         build(son[k][0],l,m),build(son[k][1],m+1,r),node[k]=node[son[k][0]]+node[son[k][1]];
    38     }
    39     void modify(int &k,int p,int l,int r,int x){
    40         k=++tot;
    41         if (l==r){node[k].init(-1);return;}
    42         int m=(l+r)>>1;
    43         if (x<=m) son[k][1]=son[p][1],modify(son[k][0],son[p][0],l,m,x);
    44         else son[k][0]=son[p][0],modify(son[k][1],son[p][1],m+1,r,x);
    45         node[k]=node[son[k][0]]+node[son[k][1]];
    46     }
    47     void modify(int id,int x){modify(root[id],root[id-1],1,n,x);}
    48     Node query(int k,int l,int r,int x,int y){
    49         if (l==x&&r==y) return node[k];
    50         int m=(l+r)>>1;
    51         if (y<=m) return query(son[k][0],l,m,x,y);
    52         else if (x<=m) return query(son[k][0],l,m,x,m)+query(son[k][1],m+1,r,m+1,y);
    53         else return query(son[k][1],m+1,r,x,y);
    54     }
    55     Node query(int id,int x,int y){return x<=y?query(root[id],1,n,x,y):(Node){-inf,-inf,-inf,0};}
    56 }T;
    57 bool check(int id){return T.query(id,t[0],t[1]).rmax+T.query(id,t[1]+1,t[2]-1).sum+T.query(id,t[2],t[3]).lmax>=0;}
    58 int solve(){
    59     int l=1,r=n,m;
    60     while (l<r){
    61         m=((l+r)>>1)+1;
    62         if (check(m)) l=m; else r=m-1;
    63     }
    64     return list[l].v;
    65 }
    66 int main(){
    67     read(n);
    68     for (int i=1;i<=n;i++) list[i].init(i);
    69     sort(list+1,list+n+1,cmp);
    70     T.build(T.root[1],1,n);
    71     for (int i=1;i<n;i++) T.modify(i+1,list[i].id);
    72     for (read(q);q;q--){
    73         for (int i=0;i<4;i++) read(t[i]),t[i]=(t[i]+ans)%n+1;
    74         sort(t,t+4),ans=solve();
    75         printf("%d
    ",ans);
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    Spring中的InitializingBean接口的使用
    解决MyBatis异常:The content of elements must consist of well-formed character data or markup.
    idea2019版与maven3.6.2版本不兼容问题
    IntelliJ IDEA更新maven依赖包
    JVM里的垃圾回收机制
    ASP.NET Core 中文文档 第四章 MVC(2.2)模型验证【转载】
    asp.net mvc Model验证总结及常用正则表达式【转载】
    SQL一次性插入大量数据【转载】
    ASP.NET Core依赖注入解读&使用Autofac替代实现【转载】
    WCF、WebAPI、WCFREST、WebService之间的区别【转载】
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5427076.html
Copyright © 2020-2023  润新知