赞
踩
给定长度为 n 的正整数序列。
有 m 组查询,每次查询区间 [a,b] 中出现次数严格大于一半的数。
即:出现次数大于等于(b-a+1)/2+1的数。
Input
第一行两个整数 n,m (1 ≤ n,m ≤ 500000),表示序列的长度和询问的个数。
接下来一行 n 个整数 p1, p2, …, pn (1 ≤ pi ≤ n),表示该序列。
接下来 m 行,每行两个整数 a,b (1 ≤ a ≤ b ≤ n),表示查询从第 a 个数到第 b 个数之间(包括两个数本身)出现次数严格大于一半的数,如果没有则输出 0.
Output
输出 m 行,对每个询问,输出一行一个整数,表示出现次数超过一半的数,如果没有则输出 0.
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
题意: 给出一个长度为n的序列以及m次询问,每次询问区间内出现次数严格大于区间长度一半的数。
分析: 比较明显的主席树题目,和主席树模板一样维护区间内权值出现次数,在查询的时候如果左区间个数大于等于目标次数就递归进左区间,如果右区间个数大于等于目标次数就递归进右区间,如果这两种情况都无法进入就直接返回0,表示无法找到符合题意的数。
这道题目这样就可以解决了,但是由于空间卡的实在是太死了,导致疯狂MLE:
最后加了个离散化水过去了,理论上数据再严格点加离散化也不应该过的......
具体代码如下:
- #include <iostream>
- #include <cstdio>
- #include <algorithm>
- #include <cstring>
- #include <cmath>
- #include <string>
- #include <vector>
- using namespace std;
-
- const int N = 5e5+5;
- struct node{
- int l, r, num;
- }tr[24*N];
- int n, m, cnt, a[N], rt[N];
- vector<int> alls;
-
- int find(int x){
- return lower_bound(alls.begin(), alls.end(), x)-alls.begin()+1;
- }
-
- int build(int l, int r){
- int id = ++cnt;
- if(l == r) return id;
- int mid = l+r>>1;
- tr[id].l = build(l, mid);
- tr[id].r = build(mid+1, r);
- return id;
- }
-
- int insert(int L, int l, int r, int x){
- int id = ++cnt;
- tr[id] = tr[L];
- tr[id].num++;
- if(l == r) return id;
- int mid = l+r>>1;
- if(x <= mid) tr[id].l = insert(tr[L].l, l, mid, x);
- else tr[id].r = insert(tr[L].r, mid+1, r, x);
- return id;
- }
-
- //寻找出现次数大于等于k的数
- int query(int L, int R, int l, int r, int k){
- if(l == r) return l;
- int mid = l+r>>1;
- int num_l = tr[tr[R].l].num-tr[tr[L].l].num;
- int num_r = tr[tr[R].r].num-tr[tr[L].r].num;
- if(num_l >= k) return query(tr[L].l, tr[R].l, l, mid, k);
- if(num_r >= k) return query(tr[L].r, tr[R].r, mid+1, r, k);
- return 0;
- }
-
- signed main()
- {
- cin >> n >> m;
- for(int i = 1; i <= n; i++){
- scanf("%d", &a[i]);
- alls.push_back(a[i]);
- }
- sort(alls.begin(), alls.end());
- alls.erase(unique(alls.begin(), alls.end()), alls.end());
- rt[0] = build(1, alls.size());
- for(int i = 1; i <= n; i++)
- rt[i] = insert(rt[i-1], 1, alls.size(), find(a[i]));
- for(int i = 1; i <= m; i++){
- int l, r, ans;
- scanf("%d%d", &l, &r);
- ans = query(rt[l-1], rt[r], 1, alls.size(), (r-l+1)/2+1);
- if(!ans) puts("0");
- else printf("%d\n", alls[ans-1]);
- }
-
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。