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 }
  • 相关阅读:
    51nod 1179 最大的最大公约数 (数论)
    POJ 3685 二分套二分
    POJ 3045 贪心
    LIC
    HDU 1029 Ignatius and the Princess IV
    HDU 1024 Max Sum Plus Plus
    HDU 2389 Rain on your Parade
    HDU 2819 Swap
    HDU 1281 棋盘游戏
    HDU 1083 Courses
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8059334.html
Copyright © 2011-2022 走看看