zoukankan      html  css  js  c++  java
  • [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哈哈~
  • 相关阅读:
    Ubuntu adb devices :???????????? no permissions (verify udev rules) 解决方法
    ubuntu 关闭显示器的命令
    ubuntu android studio kvm
    ubuntu 14.04版本更改文件夹背景色为草绿色
    ubuntu 创建桌面快捷方式
    Ubuntu 如何更改用户密码
    ubuntu 14.04 返回到经典桌面方法
    ubuntu 信使(iptux) 创建桌面快捷方式
    Eclipse failed to get the required ADT version number from the sdk
    Eclipse '<>' operator is not allowed for source level below 1.7
  • 原文地址:https://www.cnblogs.com/wls001/p/8179252.html
Copyright © 2011-2022 走看看