[BZOJ2223][BZOJ3524][Poi2014]Couriers 主席树

3524: [Poi2014]Couriers

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 2436  Solved: 960
[Submit][Status][Discuss]

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


2016.7.9重设空间,但未重测!


 

 

Source

By Dzy

 

主席树裸题

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 struct data {
 9     int ls,rs,sum;
10 }a[10000000];
11 int root[500005];
12 int n,sz=0,m;
13 void insert(int l,int r,int x,int &y,int val) {
14     y=++sz;
15     a[y].sum=a[x].sum+1;
16     if(l==r) return;
17     a[y].ls=a[x].ls;a[y].rs=a[x].rs;
18     int mid=(l+r)>>1;
19     if(val<=mid) insert(l,mid,a[x].ls,a[y].ls,val);
20     else insert(mid+1,r,a[x].rs,a[y].rs,val);
21     return ;
22 }
23 int query(int l,int r,int x,int y,int k) {
24     if(l==r) return l;
25     int mid=(l+r)>>1;
26     if(a[a[y].ls].sum-a[a[x].ls].sum>k) return query(l,mid,a[x].ls,a[y].ls,k);
27     if(a[a[y].rs].sum-a[a[x].rs].sum>k) return query(mid+1,r,a[x].rs,a[y].rs,k);
28     return 0;
29 }
30 int main() {
31     scanf("%d%d",&n,&m);
32     for(int i=1;i<=n;i++) {
33         int t;
34         scanf("%d",&t);
35         insert(1,n,root[i-1],root[i],t);
36     }
37     for(int i=1;i<=m;i++) {
38         int l,r;
39         scanf("%d%d",&l,&r);
40         int t=query(1,n,root[l-1],root[r],(r-l+1)/2);
41         printf("%d\n",t);
42     }
43 }
View Code

 

posted @ 2017-11-02 17:13  wls001  阅读(124)  评论(0编辑  收藏  举报