poj 1806 Frequent values(RMQ 统计次数) 详细讲解
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1806
题目大意:给你一个非降序排列的整数数组,你的任务是对于一系列的询问,(i,j),回答序列中出现次数最多的数的个数;
如下图所示:
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<string>
#include<cmath>
using namespace std;
const int N = 1e5+;
int a[N],b[N];
int dp[N][];
int n,m;
//构造和寻找的代码,来自大白书
void buildrmq( )
{
for(int i=;i<n;i++)
dp[i][]=b[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<n;i++)
dp[i][j]=max(dp[i][j-],dp[i+(<<(j-))][j-]);
}
int search(int s,int v)
{
int k = ;
while(<<(k+) <= v-s+) k++;
return max(dp[s][k],dp[v-(<<k)+][k]);
}
int bi_search(int s,int t)
{
int tmp=a[t];
int l=s;
int r=t;
int mid;
while(l<r)
{
mid=((l+r)>>);
if(a[mid]>=tmp) r=mid;
else l=mid+;
}
return r;
}
int main()
{
int T;
while(scanf("%d",&n) && n)
{
memset(b,,sizeof(b));
memset(dp,,sizeof(dp));
scanf("%d",&m);
for(int i =; i<n; i++)
scanf("%d",&a[i]);
a[n] = a[n-]+;
for(int i =n-; i>=; i--)//倒序统计单个数在当前段出现的次数
{
if(a[i] == a[i+])
{
b[i] = b[i+]+;
}
else b[i] =;
}
buildrmq( );//构造RMQ函数
int L,R,ans;
for(int i=; i<=m; i++)
{
scanf("%d %d",&L,&R);
L = L-;R = R-;//题目中是从1开始计数的;
int temp = bi_search(L,R);//寻找数组中最左端等于a[R]的数
ans = b[temp] - b[R]+; //统计和最左边相同的数出现的次数
if(L == temp) printf("%d\n",ans);//如果这一区间中的数字相同的话,直接左边减去右边
else printf("%d\n",max(ans,search(L,temp-)));//否则,寻找(L,temp)中的最大数,进行比较
}
}
return ;
}
AC代码2:线段树
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e5+;
int a[N];
int ans ;
struct node
{
int L,R,count,fre;
int lcount,lfre;
int rcount,rfre;
}tree[*N];
/*
l,r存该节点的边界。
count存该节点中出现最多的数字的个数,fre存该节点中出现最多的数字。
lcount 存该节点左端连续出现的数字的个数, lfre存该节点左端连续出现的数字。
rcount 存该节点右端连续出现的数字的个数, rfre存该节点右端连续出现的数字。
*/
void build(int l,int r,int v)
{
tree[v].L = l;
tree[v].R = r;
if(l == r)
{
tree[v].fre = tree[v]. rfre = tree[v].lfre = a[r];
tree[v].count = tree[v].lcount = tree[v].rcount = ;
return ;
}
int mid = (l+r)/;
build(l,mid,v*);
build(mid+,r,v*+);
int tmpc,tmpf;
if(tree[v*].count>tree[v*+].count)
{
tree[v].count = tree[v*].count;
tree[v].fre = tree[v*].fre;
}
else
{
tree[v].count = tree[v*+].count;
tree[v].fre = tree[v*+].fre;
}
tree[v].lcount = tree[v*].lcount;
tree[v].rcount = tree[v*+].rcount;
if(tree[v*].rfre == tree[v*+].lfre)
{
tmpc = tree[v*].rcount +tree[v*+].lcount;
tmpf = tree[v*].rfre;
if(tree[v].count<tmpc)
{
tree[v].count = tmpc;
tree[v].fre = tmpf;
}
if(tree[v*].lfre == tree[v*+].lfre)
tree[v].lcount = tree[v].lcount+tree[v*+].lcount;
if(tree[v*].rfre == tree[v*+].rfre)
tree[v].rcount= tree[v*].rcount+tree[v].rcount;
}
tree[v].lfre = tree[v*].lfre;
tree[v].rfre = tree[v*+].rfre;
}
void update(int x,int y,int v)
{
int mid,s1,s2;
if(tree[v].L == x && tree[v].R == y)
{
if(tree[v].count>ans)
ans = tree[v].count;
return ;
}
mid = (tree[v].L+tree[v].R)/;
if(y<=mid) update(x,y,v*);
else if(x>mid) update(x,y,v*+);
else {
update(x,mid,v*);
update(mid+,y,v*+);
if(tree[v*].rfre == tree[v*+].lfre)
{
if(a[x] != tree[v*].rfre) s1 = tree[v*].rcount;
else s1 = mid-x+;
if(a[y]!=tree[v*+].lfre) s2 = tree[v*+].lcount;
else s2 = y - mid;
if(s1+s2>ans) ans = s1+s2;
}
}
}
int main()
{
int m,n,x,y;
while(scanf("%d",&m) && m)
{
scanf("%d\n",&n);
for(int i=;i<=m;i++)
scanf("%d",&a[i]);
build(,m,);
for(int i=;i<=n; i++)
{ ans = ;
scanf("%d %d",&x,&y);
if(x==y) {printf("1\n");continue;}
update(x,y,);
printf("%d\n",ans);
}
}
return ;
}
poj 1806 Frequent values(RMQ 统计次数) 详细讲解的更多相关文章
- poj 3368 Frequent values(RMQ)
/************************************************************ 题目: Frequent values(poj 3368) 链接: http ...
- POJ 3368 Frequent values RMQ ST算法/线段树
Frequent values Time Limit: 2000MS Memory Lim ...
- POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)
题目链接:http://poj.org/problem? id=3368 Description You are given a sequence of n integers a1 , a2 , .. ...
- POJ 3368 Frequent values RMQ 训练指南 好题
#include<cstdio> #include<cstring> ; const int inf=0x3f3f3f3f; inline int max(int x,int ...
- RMQ算法 以及UVA 11235 Frequent Values(RMQ)
RMQ算法 简单来说,RMQ算法是给定一组数据,求取区间[l,r]内的最大或最小值. 例如一组任意数据 5 6 8 1 3 11 45 78 59 66 4,求取区间(1,8) 内的最大值.数据量小 ...
- POJ 3368 Frequent values (基础RMQ)
Frequent values Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14742 Accepted: 5354 ...
- POJ 3368 Frequent values 【ST表RMQ 维护区间频率最大值】
传送门:http://poj.org/problem?id=3368 Frequent values Time Limit: 2000MS Memory Limit: 65536K Total S ...
- [HDU 1806] Frequent values
Frequent values Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- poj 3368 Frequent values(段树)
Frequent values Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13516 Accepted: 4971 ...
随机推荐
- pca主成份分析方法
1.应用pca的前提 应用pca的前提是,连续信号具有相关性.相关性是什么,是冗余.就是要利用pca去除冗余. 2.pca的定义 pca是一种去除随机变量间相关性的线性变换.是一种常用的多元数据分析方 ...
- Mybatis数据库操作的返回值
mybatis配置 <!-- 配置mybatis --> <bean id="sqlSessionFactory" class="org.mybatis ...
- WAF攻击与防御
背景 对于腾讯的业务来说,有两个方面决定着WAF能否发挥效果,一个是合适处理海量流量的架构,另一个关键因素则是规则系统.架构决定着WAF能否承受住海量流量的挑战,这个在之前的篇章中简单介绍过(详情见主 ...
- SQL盲注攻击的简单介绍
1 简介 1.1 普通SQL注入技术概述 目前没有对SQL注入技术的标准定义,微软中国技术中心从2个方面进行了描述[1]: (1) 脚本注入式的攻击 (2) 恶意用户输 ...
- sqlserver中事务总结:begin tran,rollback tran,commit tran
第1个相关用法:摘自:https://shiyousan.com/post/f13d29b7-0d87-4168-bd8b-8b28b0991b5a 以下是出现错误的SQL部分语句: 此错误的原因是 ...
- TensorFlow环境搭建及安装教程
1.安装虚拟环境virtualenv相关配置(创建了python3.5的环境) 2.http://docs.nvidia.com/cuda/cuda-installation-guide-linux/ ...
- 不输入sudo使用docker
系统是debian系 安装: sudo apt install docker.io 将当前用户加入‘docker’组: sudo gpasswd -a ${USER} docker 刷新权限: su ...
- 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何修改某个轴的数值单位
在某个轴上双击,切换到Settings,然后可以再Unit中修改为角度,弧度,mm 更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com/aceta ...
- array_intersect_assoc用法详解
最近在做考试系统,想到这个数组函数,用法如下: <?php $a1=array('a','b','d','c','d','b','c','a'); $a2=array('b','d','d',' ...
- 一直加载“fonts.googleapis.com”的解决办法
原文:http://www.tuicool.com/articles/6bayeq 最近国内对google又开始了新一轮的屏蔽,很多wordpress用户发现一个现象,那就是网站前台和后台打开都非常慢 ...