zoukankan      html  css  js  c++  java
  • bzoj 2653 middle (可持久化线段树)

    middle

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 1981  Solved: 1097
    [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

     
    题解:
      十分经典啊,好题,中位数的题目,以后可以想到二分去解决。
      就是比中位数大的变1,小的为-1,则sum>=0即可判断是否可以比当前二分的
      中位数更大,然后就可以,所以对于从小到大,开n个不同状态的线段树,这样就可以了。
      1 #include<cstring>
      2 #include<cmath>
      3 #include<algorithm>
      4 #include<iostream>
      5 #include<cstdio>
      6 
      7 #define lson tr[p].ls
      8 #define rson tr[p].rs
      9 #define N 20007
     10 using namespace std;
     11 inline int read()
     12 {
     13     int x=0,f=1;char ch=getchar();
     14     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
     15     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 
     19 int n,m,sz,ans;
     20 int a[N],id[N],rt[N];
     21 struct Node
     22 {
     23     int sum,lmx,rmx,ls,rs;
     24 }tr[N*20];
     25 
     26 bool cmp(int x1,int x2)
     27 {
     28     return a[x1]<a[x2];
     29 }
     30 void update(int p)
     31 {
     32     tr[p].sum=tr[lson].sum+tr[rson].sum;
     33     tr[p].lmx=max(tr[lson].lmx,tr[lson].sum+tr[rson].lmx);
     34     tr[p].rmx=max(tr[rson].rmx,tr[rson].sum+tr[lson].rmx);
     35 }
     36 void build(int &p,int l,int r)
     37 {
     38     p=++sz;
     39     if (l==r)
     40     {
     41         tr[p].sum=tr[p].lmx=tr[p].rmx=1;
     42         return;
     43     }
     44     int mid=(l+r)>>1;
     45     build(tr[p].ls,l,mid),build(tr[p].rs,mid+1,r);
     46     update(p);
     47 }
     48 void build_new(int yl,int l,int r,int &xz,int val,int z)
     49 {
     50     xz=++sz;tr[xz]=tr[yl];
     51     if (l==r)
     52     {
     53         tr[xz].lmx=tr[xz].rmx=tr[xz].sum=val;
     54         return;
     55     }
     56     int mid=(l+r)>>1;
     57     if (z<=mid) build_new(tr[yl].ls,l,mid,tr[xz].ls,val,z);
     58     else build_new(tr[yl].rs,mid+1,r,tr[xz].rs,val,z);
     59     update(xz);
     60 }
     61 int get_sum(int p,int l,int r,int x,int y)
     62 {
     63     if (l==x&&r==y) return tr[p].sum;
     64     int mid=(l+r)>>1;
     65     if (y<=mid) return get_sum(tr[p].ls,l,mid,x,y);
     66     else if (x>mid) return get_sum(tr[p].rs,mid+1,r,x,y);
     67     else return get_sum(tr[p].ls,l,mid,x,mid)+get_sum(tr[p].rs,mid+1,r,mid+1,y);
     68 }
     69 int get_rx(int p,int l,int r,int x,int y)
     70 {
     71     if (l==x&&r==y) return tr[p].lmx;
     72     int mid=(l+r)>>1;
     73     if (y<=mid) return get_rx(tr[p].ls,l,mid,x,y);
     74     else if (x>mid) return get_rx(tr[p].rs,mid+1,r,x,y);
     75     else return max(get_rx(tr[p].ls,l,mid,x,mid),get_sum(tr[p].ls,l,mid,x,mid)+get_rx(tr[p].rs,mid+1,r,mid+1,y));
     76 }
     77 int get_lx(int p,int l,int r,int x,int y)
     78 {
     79     if (l==x&&r==y) return tr[p].rmx;
     80     int mid=(l+r)>>1;
     81     if (y<=mid) return get_lx(tr[p].ls,l,mid,x,y);
     82     else if (x>mid) return get_lx(tr[p].rs,mid+1,r,x,y);
     83     else return max(get_lx(tr[p].rs,mid+1,r,mid+1,y),get_sum(tr[p].rs,mid+1,r,mid+1,y)+get_lx(tr[p].ls,l,mid,x,mid));
     84 }
     85 bool check(int k,int a,int b,int c,int d)
     86 {
     87     int sum=0;
     88     if (b+1<=c-1) sum+=get_sum(rt[k],1,n,b+1,c-1);
     89     sum+=get_lx(rt[k],1,n,a,b);
     90     sum+=get_rx(rt[k],1,n,c,d);
     91     return sum>=0;//大的个数多的话那么可以找更大的中位数、 
     92 }
     93 int main()
     94 {
     95     n=read();
     96     for (int i=1;i<=n;i++)
     97         a[i]=read(),id[i]=i;
     98     sort(id+1,id+n+1,cmp);
     99     build(rt[1],1,n);    
    100     for (int i=2;i<=n;i++)
    101         build_new(rt[i-1],1,n,rt[i],-1,id[i-1]);
    102     int qz[5];
    103     m=read();
    104     while(m--)
    105     {
    106         qz[1]=read(),qz[2]=read(),qz[3]=read(),qz[4]=read();
    107         for (int i=1;i<=4;i++)
    108             qz[i]=(qz[i]+ans)%n;
    109         for (int i=1;i<=4;i++)
    110             qz[i]+=1;
    111         sort(qz+1,qz+4+1);
    112         int l=1,r=n,mid;
    113         while(l<r)
    114         {
    115             mid=(l+r+1)>>1;
    116             if (check(mid,qz[1],qz[2],qz[3],qz[4])) l=mid;
    117             else r=mid-1;
    118         }
    119         ans=a[id[l]];
    120         printf("%d
    ",ans);
    121     }
    122 }
  • 相关阅读:
    project b2c_performance / capacity
    WebServer Roxen
    OS + UNIX AIX /etc/services
    但行好事,莫问前程 All In One
    学习什么语言的问题,其实,不是一个问题......
    不想当将军的学生,不是好程序员——数据访问层DAL
    C#如何用Graphics画出一幅图表
    混蛋的面试题——《大话设计模式》读后感
    编程也讲禅,您读过《金刚经》吗?——ADO.NET核心类的灭度与SQLHelper的诞生——十八相送(上)
    C#如何开发扫雷游戏
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8059334.html
Copyright © 2011-2022 走看看