1. 程式人生 > >【bzoj 3524】[Poi2014]Couriers

【bzoj 3524】[Poi2014]Couriers

build oid 存在 show poi2014 namespace class 出現的次數 mil

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

【bzoj 3524】[Poi2014]Couriers