[bzoj3524/2223][Poi2014]Couriers_主席树

Couriers bzoj-3524 Poi-2014

题目大意:给定n个数的序列,询问区间内是否存在一个在区间内至少出现了(区间长度>>1)次的数。如果有,输出该数,反之输出0。

注释:$1\le n,m\le 5\cdot 10^5$。


想法:主席树裸题。

主流做法就是弄一个Existence数组询问有没有这样的数,然后查询区间中位数即可。

但是可以在query的时候强行查询,因为没有输出0,直接输出即可。

最后,附上丑陋的代码... ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 500010
using namespace std;
int cnt[N<<5],ls[N<<5],rs[N<<5],tot;
int a[N],b[N],root[N];
int build(int l,int r)
{
    int pos=++tot,mid=(l+r)>>1;
    if(l==r) return pos;
    ls[pos]=build(l,mid); rs[pos]=build(mid+1,r);
    return pos;
}
int update(int pre,int l,int r,int k)
{
    int pos=++tot,mid=(l+r)>>1;
    cnt[pos]=cnt[pre]+1;
    ls[pos]=ls[pre]; rs[pos]=rs[pre];
    if(l==r) return pos;
    if(k<=mid) ls[pos]=update(ls[pre],l,mid,k);
    else rs[pos]=update(rs[pre],mid+1,r,k);
    return pos;
}
// bool Existence(int x,int y,int l,int r,int Want)
// {
//  if(l==r) return (cnt[y]-cnt[x])>=Want;
//  int mid=(l+r)>>1;
//  int LR=1;
//  if(cnt[ls[y]]-cnt[ls[x]]>cnt[rs[y]]-cnt[rs[x]]) LR=0;
//  else if(cnt[ls[y]]-cnt[ls[x]]<cnt[rs[y]]-cnt[rs[x]]) LR=2;
//  if(LR==0) return Existence(ls[x],ls[y],l,mid,Want);
//  if(LR==2) return Existence(rs[x],rs[y],mid+1,r,Want);
//  return Existence(ls[x],ls[y],l,mid,Want)|Existence(rs[x],rs[y],mid+1,r,Want);
// }
// int query(int x,int y,int l,int r,int k)
// {
//  int mid=(l+r)>>1;
//  if(l==r) return b[l];
//  int dlt=cnt[ls[y]]-cnt[ls[x]];
//  if(dlt>=k) return query(ls[x],ls[y],l,mid,k);
//  else return query(rs[x],rs[y],mid+1,r,k-dlt);
// }
int query(int x,int y,int l,int r,int k)
{
    int mid=(l+r)>>1;
    if(l==r) return l;
    int L=cnt[ls[y]]-cnt[ls[x]],R=cnt[rs[y]]-cnt[rs[x]];
    if(L>k) return query(ls[x],ls[y],l,mid,k);
    if(R>k) return query(rs[x],rs[y],mid+1,r,k);
    else return 0;
}
int main()
{
    int n,m; cin >> n >> m ;
    for(int i=1;i<=n;i++) scanf("%d",&a[i])/* ,b[i]=a[i] */;
    sort(b+1,b+n+1); /* int len=unique(b+1,b+n+1)-b-1; */
    root[0]=build(1,n);
    for(int i=1;i<=n;i++)
    {
        // int t=lower_bound(b+1,b+n+1,a[i])-b;
        root[i]=update(root[i-1],1,n,a[i]);
    }
    for(int x,y,i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        // if(Existence(root[x-1],root[y],1,n,(y-x+1)/2+1)) printf("%d\n",query(root[x-1],root[y],1,n,(y-x+1)/2+1));
        // else printf("0\n");
        printf("%d\n",query(root[x-1],root[y],1,n,(y-x+1)>>1));
    }
    return 0;
}

小结:主席树真强... ...

posted @   JZYshuraK_彧  阅读(169)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示