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 }
时间: 2024-11-10 05:26:37