• BZOJ2223/3524:[POI2014] Couriers(主席树)


    Description

    给一个长度为n的序列a。1≤a[i]≤n。
    m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

    Input

    第一行两个数n,m。
    第二行n个数,a[i]。
    接下来m行,每行两个数l,r,表示询问[l,r]这个区间。

    Output

    m行,每行对应一个答案。

    Sample Input

    7 5
    1 1 3 2 3 4 3
    1 3
    1 4
    3 7
    1 7
    6 6

    Sample Output

    1
    0
    3
    0
    4

    HINT

    【数据范围】

    n,m≤500000

    Solution

    就是递归查询区间sum是否大于(r-l+1)/2,是的话就递归左右儿子,否则return
    如果能一直递归到l==r就是有解,否则无解

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define N (300000+100)
     6 using namespace std;
     7 struct node{int lson,rson,sum;}Segt[N*40];
     8 int a[N],b[N],n,m,Root[N],Segt_cnt,x,y,lim;
     9 
    10 int Build(int l,int r)
    11 {
    12     int node=++Segt_cnt;
    13     if (l==r) return node;
    14     int mid=(l+r)>>1;
    15     Segt[node].lson=Build(l,mid);
    16     Segt[node].rson=Build(mid+1,r);
    17     return node;
    18 }
    19 
    20 int Update(int pre,int l,int r,int x)
    21 {
    22     int node=++Segt_cnt;
    23     Segt[node].sum=Segt[pre].sum+1;
    24     Segt[node].lson=Segt[pre].lson;
    25     Segt[node].rson=Segt[pre].rson;
    26     if (l==r) return node;
    27     int mid=(l+r)>>1;
    28     if (x<=mid) Segt[node].lson=Update(Segt[node].lson,l,mid,x);
    29     else Segt[node].rson=Update(Segt[node].rson,mid+1,r,x);
    30     return node;
    31 }
    32 
    33 int Query(int u,int v,int l,int r)
    34 {
    35     int mid=(l+r)>>1,c=Segt[v].sum-Segt[u].sum;
    36     if (c<=(y-x+1)>>1) return 0;
    37     if (l==r) return b[l];    
    38     return max(Query(Segt[u].lson,Segt[v].lson,l,mid),Query(Segt[u].rson,Segt[v].rson,mid+1,r));
    39 }
    40 
    41 int main()
    42 {
    43     scanf("%d%d",&n,&lim);
    44     for (int i=1;i<=n;++i)
    45         scanf("%d",&a[i]),b[i]=a[i];
    46     sort(b+1,b+n+1);
    47     int num=unique(b+1,b+n+1)-b-1;
    48     Root[0]=Build(1,num);
    49     for (int i=1;i<=n;++i)
    50     {
    51         int t=lower_bound(b+1,b+num+1,a[i])-b;
    52         Root[i]=Update(Root[i-1],1,num,t);
    53     }
    54     scanf("%d",&m);
    55     for (int i=1;i<=m;++i)
    56     {
    57         scanf("%d%d",&x,&y);
    58         int ans=Query(Root[x-1],Root[y],1,num);
    59         if (ans) printf("yes %d
    ",ans);
    60         else printf("no
    ");
    61     }
    62 }
  • 相关阅读:
    45套精美的 ( Android, iPhone, iPad ) 手机界面设计素材和线框图设计工具
    JAVA基础01
    这是我的第一个博客
    string(更新)
    KMP
    标准C++中的string类的用法总结
    coj 数学作业(300)
    异或的性质及运用
    substr在oracle和mysql中的应用和区别
    非空校验在oracle和mysql中的用法
  • 原文地址:https://www.cnblogs.com/refun/p/8685685.html
Copyright © 2020-2023  润新知