[POI2014]KUR-Couriers
来源:互联网 发布:雅居乐找软件测试 编辑:程序博客网 时间:2024/06/08 13:52
题意
给一个数列,每次询问一个区间内有没有一个数出现次数超过一半
题解
主席树,一个数出现次数>一半,这个区间内只有这一个数满足,那么主席树直接维护所有数的出现次数,直接在树上二分查询
# include <bits/stdc++.h># define RG register# define IL inline# define Fill(a, b) memset(a, b, sizeof(a))using namespace std;typedef long long ll;const int _(500010), __(1e7);IL ll Read(){ RG char c = getchar(); RG ll x = 0, z = 1; for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z;}int n, m, p[_], id[_], len, rt[__], ls[__], rs[__], sz[__], cnt;IL void Build(RG int &x, RG int l, RG int r){ x = ++cnt; if(l == r) return; RG int mid = (l + r) >> 1; Build(ls[x], l, mid); Build(rs[x], mid + 1, r);}IL void Modify(RG int &x, RG int l, RG int r, RG int pos){ sz[++cnt] = sz[x]; ls[cnt] = ls[x]; rs[cnt] = rs[x]; sz[x = cnt]++; if(l == r) return; RG int mid = (l + r) >> 1; if(pos <= mid)Modify(ls[x], l, mid, pos); else Modify(rs[x], mid + 1, r, pos);}IL int Query(RG int A, RG int B, RG int l, RG int r, RG int half){ if(l == r) return l; RG int sum1 = sz[ls[B]] - sz[ls[A]], sum2 = sz[rs[B]] - sz[rs[A]], mid = (l + r) >> 1; if(sum1 > half) return Query(ls[A], ls[B], l, mid, half); if(sum2 > half) return Query(rs[A], rs[B], mid + 1, r, half); return 0;}int main(RG int argc, RG char* argv[]){ n = Read(); m = Read(); for(RG int i = 1; i <= n; i++) id[i] = p[i] = Read(); sort(p + 1, p + n + 1); len = unique(p + 1, p + n + 1) - p - 1; Build(rt[0], 1, len); for(RG int i = 1; i <= n; i++){ id[i] = lower_bound(p + 1, p + len + 1, id[i]) - p; rt[i] = rt[i - 1]; Modify(rt[i], 1, len, id[i]); } for(RG int i = 1, l, r; i <= m; i++) l = Read(), r = Read(), printf("%d\n", Query(rt[l - 1], rt[r], 1, len, (r - l + 1) >> 1)); return 0;}
阅读全文