BZOJ3524 [Poi2014]Couriers

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3524

题目大意:给一个长度为n的序列a。1≤a[i]≤n。
     m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

题解:感觉这种题,随便搞啊,莫队什么的,主席树也可以啊,就当复习主席树咯

代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #define maxn 500010
 7 using namespace std;
 8 int root[maxn],ls[maxn*20],rs[maxn*20];
 9 int sum[maxn*20];
10 int n,m;
11 int sz;
12 int read()
13 {
14     int x=0; char ch; bool bo=0;
15     while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1;
16     while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
17     if (bo) return -x; return x;
18 }
19 void ins(int l,int r,int x,int &y,int val)
20 {
21     y=++sz;
22     sum[y]=sum[x]+1; 
23     if (l==r) return;
24     ls[y]=ls[x],rs[y]=rs[x];
25     int mid=(l+r)>>1;
26     if (val<=mid) ins(l,mid,ls[x],ls[y],val);
27     else ins(mid+1,r,rs[x],rs[y],val);
28 }
29 int query(int L,int R)
30 {
31     int l=1,r=n,mid,x,y,tmp;
32     x=root[L-1],y=root[R];
33     tmp=(R-L+1)/2;
34     //cout<<"         "<<tmp<<endl;
35     while (l!=r)
36     {
37         if (sum[y]-sum[x]<=tmp) return 0;
38         int mid=(l+r)>>1;
39         if (sum[ls[y]]-sum[ls[x]]>tmp) 
40         {
41             r=mid; y=ls[y],x=ls[x];
42         }
43         else
44         if (sum[rs[y]]-sum[rs[x]]>tmp)
45         {
46             l=mid+1,y=rs[y],x=rs[x];
47         }
48         else return 0;
49     }
50     return l;
51 }
52 
53 int main()
54 {
55     n=read(); m=read();
56     for (int i=1; i<=n; i++)
57     {
58         int x=read();
59         ins(1,n,root[i-1],root[i],x);
60     }
61     for (int i=1; i<=m ;i++)
62     {
63         int l=read(),r=read();
64         int ans=query(l,r);
65         printf("%d
",ans);
66     }
67 }
View Code
原文地址:https://www.cnblogs.com/HQHQ/p/5595155.html