zoukankan      html  css  js  c++  java
  • BZOJ 2653 middle 题解

    题意:一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。

    给一个序列,并进行一些询问。每次询问起点在[a,b],终点在[c,d]的序列的中位数。

    题解:首先有一个思路:对于一个序列S,假设它的中位数是m,则S中>=m的元素个数一定>=n

    那么对于一个序列S和一个数m,我们将>=m的元素设置为1,其余为-1,得到一个新数列S‘。则$sum S'$ >=0

    对于每个询问我们二分一下m即可。如果在区间[a,d]内有一段包含[b,c]的连续子序列的和>=0,则答案>=当前二分的值。

    求最大子序列的和相信大家都会做。。用线段树维护lmax,rmax,sum值即可

    但是如果每次都暴力构建线段树的话太慢了。。和暴力差不了多少

    于是我们可以用可持久化线段树做。。

    然后这题就解决了。。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define fr first
     4 #define sc second
     5 const int MAXN=20000+5;
     6 const int INF=~0U>>1;
     7 struct Info{
     8     int sum,maxl,maxr;
     9     Info(int v) {sum=maxl=maxr=v;}
    10     Info() {}
    11 };
    12 Info operator+(const Info& a,const Info& b)
    13 {
    14     Info ans;
    15     ans.sum=a.sum+b.sum;
    16     ans.maxl=std::max(a.maxl,a.sum+std::max(0,b.maxl));
    17     ans.maxr=std::max(b.maxr,b.sum+std::max(0,a.maxr));
    18     return ans;
    19 }
    20 struct Tree{
    21     int l,r;
    22     Info v;
    23     Tree* pl,*pr;
    24     Tree(int l,int r,int all):l(l),r(r)
    25     {
    26         if(l+1==r)
    27         {
    28             v=Info(all);
    29             return;
    30         }
    31         int m=(l+r)>>1;
    32         pl=new Tree(l,m,all);
    33         pr=new Tree(m,r,all);
    34         v=pl->v+pr->v;
    35     }
    36     Tree(int l,int r,Tree* pl,Tree* pr):l(l),r(r),pl(pl),pr(pr) {v=pl->v+pr->v;}
    37     Info query(int L,int R)
    38     {
    39         if(L<=l && R>=r) return v;
    40         int m=(l+r)>>1;
    41         if(R<=m) return pl->query(L,R);
    42         else if(L>=m) return pr->query(L,R);
    43         else return pl->query(L,R)+pr->query(L,R);
    44     }
    45     Tree* change(int pos,int w)
    46     {
    47         if(l+1==r) return new Tree(l,r,w);
    48         int m=(l+r)>>1;
    49         if(pos<m) return new Tree(l,r,pl->change(pos,w),pr);
    50         else return new Tree(l,r,pl,pr->change(pos,w));
    51     }
    52 };
    53 typedef std::pair<int,int> P;
    54 P ps[MAXN];
    55 Tree* root[MAXN];
    56 int n;
    57 inline bool judge(int v,int a,int b,int c,int d)    //[a,b) [c,d)
    58 {
    59     Tree* r=root[v];
    60     return (r->query(a,b).maxr+(b<c?r->query(b,c).sum:0)+r->query(c,d).maxl)>=0;
    61 }
    62 int main()
    63 {
    64     scanf("%d",&n);
    65     for(int i=0;i<n;++i)
    66     {
    67         int t;
    68         scanf("%d",&t);
    69         ps[i]=P(t,i);
    70     }
    71     std::sort(ps,ps+n);
    72     root[0]=new Tree(0,n,1);
    73     for(int i=1;i<n;++i)
    74         root[i]=root[i-1]->change(ps[i-1].sc,-1);
    75     int q,last=0;
    76     scanf("%d",&q);
    77     while(q--)
    78     {
    79         int t[4];
    80         for(int i=0;i<4;++i) scanf("%d",t+i),t[i]=(t[i]+last)%n;
    81         std::sort(t,t+4);
    82         int l=0,r=n;
    83         while(l+1<r)
    84         {
    85             int m=(l+r)>>1;
    86             if(judge(m,t[0],t[1]+1,t[2],t[3]+1)) l=m;
    87             else r=m;
    88         }
    89         printf("%d
    ",ps[l].fr);
    90         last=ps[l].fr;
    91     }
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    MSP430:输入捕获
    MSP430:串口输出
    测试输出时钟频率
    C# MySql Select
    C# MySql 连接
    MSP430:PWM产生
    MSP430:定时器学习TimerA
    MSP430:中断简介
    MSP430 PIN 操作寄存器
    剑指offer---包含min函数的栈
  • 原文地址:https://www.cnblogs.com/lowsfish/p/4429315.html
Copyright © 2011-2022 走看看