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
  • 相关阅读:
    leetcode 29-> Divide Two Integers without using multiplication, division and mod operator
    ros topic 发布一次可能会接收不到数据
    python中的print()、str()和repr()的区别
    python 部分函数
    uiautomatorviewer错误 unable toconnect to adb
    pyqt 不规则形状窗口显示
    appium 计算器demo
    Spring 3.0 注解注入详解
    Spring Autowire自动装配
    restful 学习地址
  • 原文地址:https://www.cnblogs.com/lowsfish/p/4429315.html
Copyright © 2011-2022 走看看