【bzoj 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

 

主席树模板题。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=5e5+5;
 6 int n,m,sz,cnt,tmp,id,Li,Ri,a[N],b[N],rt[N];
 7 struct node{int sum,lc,rc;}tr[N*20];
 8 int read()
 9 {
10     int x=0,f=1;char c=getchar();
11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
13     return x*f;
14 }
15 void build(int& root,int L,int R)
16 {
17     root=++cnt;tr[root].sum=0;
18     if(L==R)return;int mid=(L+R)>>1;
19     build(tr[root].lc,L,mid);build(tr[root].rc,mid+1,R);
20 }
21 void up(int& root,int L,int R,int last,int num)
22 {
23     root=++cnt;tr[root]=(node){tr[last].sum+1,tr[last].lc,tr[last].rc};
24     if(L==R)return;int mid=(L+R)>>1;
25     if(num<=mid)up(tr[root].lc,L,mid,tr[last].lc,num);
26     else up(tr[root].rc,mid+1,R,tr[last].rc,num);
27 }
28 int query(int ql,int qr,int L,int R,int K)
29 {
30     if(L==R){if(tr[qr].sum-tr[ql].sum>=K)return L;return 0;}
31     int mid=(L+R)>>1;
32     tmp=tr[tr[qr].lc].sum-tr[tr[ql].lc].sum;
33     if(tmp>=K)return query(tr[ql].lc,tr[qr].lc,L,mid,K);
34     else return query(tr[ql].rc,tr[qr].rc,mid+1,R,K);
35 }
36 void work()
37 {
38     Li=read();Ri=read();
39     id=query(rt[Li-1],rt[Ri],1,sz,(Ri-Li+1)/2+1);
40     printf("%d\n",b[id]);
41 }
42 int main()
43 {
44     n=read();m=read();
45     for(int i=1;i<=n;i++)a[i]=b[i]=read();
46     sort(b+1,b+n+1);sz=unique(b+1,b+n+1)-b-1;
47     build(rt[0],1,sz);
48     for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+sz+1,a[i])-b;
49     for(int i=1;i<=n;i++)up(rt[i],1,sz,rt[i-1],a[i]);
50     while(m--)work();
51     return 0;
52 }
View Code

 

posted @ 2017-12-22 21:04  Zsnuo  阅读(194)  评论(0编辑  收藏  举报