BZOJ 3524: [Poi2014]Couriers
题目大意:
给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
题解:
如果这个数存在,那么这个数存在的区间中数的个数必定大于(r-l+1)/2,这里的区间以数值为下标。我们开一棵主席树然后在主席树上二分就可以找到这个数了。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #include<cstdio> using namespace std; int n,q,cnt,root[1000005],tree[10000005],ls[10000005],rs[10000005]; void insert( int &now, int pre, int l, int r, int x){ now=++cnt; tree[now]=tree[pre]+1; if (l==r) return ; int mid=(l+r)>>1; ls[now]=ls[pre],rs[now]=rs[pre]; if (x<=mid) insert(ls[now],ls[pre],l,mid,x); else insert(rs[now],rs[pre],mid+1,r,x); } int query( int l, int r){ int L=1,R=n,key=(r-l+1)>>1; int x=root[l-1],y=root[r]; while (L<R){ if (tree[y]-tree[x]<=key) return 0; int mid=(L+R)>>1; if (tree[ls[y]]-tree[ls[x]]>key){ R=mid; x=ls[x]; y=ls[y]; } else { L=mid+1; x=rs[x]; y=rs[y]; } } if (tree[y]-tree[x]<=key) return 0; else return L; } int main(){ scanf ( "%d%d" ,&n,&q); for ( int i=1; i<=n; i++){ int x; scanf ( "%d" ,&x); insert(root[i],root[i-1],1,n,x); } while (q--){ int l,r; scanf ( "%d%d" ,&l,&r); printf ( "%d\n" ,query(l,r)); } return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步