POJ 3368 Frequent values(线段树)
来源:互联网 发布:淘宝外围会场有用吗 编辑:程序博客网 时间:2024/06/05 19:23
题意:给出一个大小为n的非降序数字序列,查询区间内出现次数最多的数字出现的次数
思路:如何建树比较难想,建树前需要一些处理
观察一下,数字的范围为-100000-100000,给出的顺序非降序
让每个出现过的数字对应一个区间,a[ ]记录序列,
th[ ] 记录某个位置的数字是出现的第几个数字,cnt[ ]记录这个数字出现的次数,用cnt[ ] 建线段树记录最大值,l[ ] 记录这个数字出现的第一个位置,r[ ]记录出现的最后一个位置
查询时将区间分为三个部分:
一、th[i] + 1 到 th[j] - 1 这几个数字的cnt最大值,查询线段树;
二、th[i] 这个数在查询区间出现的次数,r [ th[ i ] ] - i + 1;
三、 th[j]这个数在查询区间出现的次数,j - l [ th[ j ] ] + 1;
#include <stdio.h>#include <string.h>#include <algorithm>#define lson l, m, rt * 2#define rson m + 1, r, rt * 2 + 1int a[100010], th[100010], cnt[100010];int l[100010], r[100010];int max[100010 * 4];void pushup(int rt){ max[rt] = max[rt * 2] > max[rt * 2 + 1] ? max[rt * 2] : max[rt * 2 + 1];}void build(int l, int r, int rt){ if(l == r) { max[rt] = cnt[l]; return; } int m = (l + r) / 2; build(lson); build(rson); pushup(rt);}int query(int L, int R, int l, int r, int rt){ if(L <= l && r <= R) { return max[rt]; } int m = (l + r) / 2; int lmax = 0, rmax = 0; if(L <= m) lmax = query(L, R, lson); if(R > m) rmax = query(L, R, rson); return lmax > rmax ? lmax : rmax;}int main(){ #ifdef LOCAL freopen("data.in", "r", stdin); #endif int n, q; while(scanf("%d", &n) != EOF) { if(n == 0) break; scanf("%d", &q); for(int i = 0; i < n; i++) { scanf("%d", &a[i]); } memset(th, 0, sizeof(th)); memset(cnt, 0, sizeof(cnt)); memset(l, 0, sizeof(l)); memset(r, 0, sizeof(r)); memset(max, 0, sizeof(max)); th[0] = 1; cnt[1] = 1; l[1] = 0; r[1] = 0; int k = 1; for(int i = 1; i < n; i++) { //得到th[],cnt[],l[],r[] if(a[i] == a[i - 1]) { th[i] = k; cnt[k]++; r[k] = i; } else { k++; th[i] = k; cnt[k] = 1; l[k] = i; r[k] = i; } } build(1, k, 1); int x, y, ans; while(q--) { scanf("%d%d", &x, &y); x--; y--; if(th[x] == th[y]) { ans = y - x + 1; //printf("1:%d %d: %d\n", x, y, ans); } else if(th[x] + 1 == th[y]) { ans = (r[th[x]] - x + 1) > (y - l[th[y]] + 1) ? (r[th[x]] - x + 1) : (y - l[th[y]] + 1); //printf("2:%d %d: %d\n", x, y, ans); } else { //分三部分查询 ans = query(th[x] + 1, th[y] - 1, 1, k, 1); if(r[th[x]] - x + 1 > ans) ans = r[th[x]] - x + 1; if(y - l[th[y]] + 1 > ans) ans = y - l[th[y]] + 1; //printf("3:%d %d: %d\n", x, y, ans); } printf("%d\n", ans); } } return 0;}
0 0
- POJ 3368 Frequent values(线段树)
- poj 3368 Frequent values(线段树)
- POJ 3368 Frequent values(线段树)
- poj-3368-Frequent values-(线段树)
- poj 3368 Frequent values //线段树
- poj 3368 --Frequent values 线段树
- POJ 3368 Frequent values RMQ / 线段树
- poj 3368 Frequent values(线段树)
- POJ 3368 Frequent values 线段树
- poj 3368 Frequent values#线段树
- POJ 3368 Frequent values 线段树
- poj-3368 Frequent values 线段树
- 【poj 3368 】 Frequent values 线段树应用
- poj 3368 Frequent values 线段树
- poj 3368 Frequent values 线段树
- POJ 3368 Frequent values 线段树 || RMQ
- poj 3368 Frequent values(线段树解法)
- POJ 3368 Frequent values(线段树区间合并)
- 使用backtrace和backtrace_symbols打印函数调用链
- 文章标题
- SSD 之Trim指令
- Android设置透明、半透明等效果
- hdoj 2603 Wiskey's Power 【物理题。。。】
- POJ 3368 Frequent values(线段树)
- 改进型Clock算法
- linux进程调度CFS
- 通过分析 JDK 源代码研究 Hash 存储机制
- C++中深拷贝和浅拷贝
- uIP协议栈初步认识
- struts2中constants参数配置
- Drag/Drop---突袭HTML5之Javascript API扩展4 - 拖拽
- 浏览博客请前往http://hehaiyang.cnblogs.com