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 ...
随机推荐
- windows2012 IIS部署GeoTrust证书踩过的坑。
系统:windows2012 环境:IIS8 在阿里云上买了GeoTrust证书, 按照说明下载证书到服务器, 导入证书, 给IIS站点部署https. 阿里云部署帮助文档:https://help ...
- MS SQL 标识列的查询
摘自: http://www.2cto.com/database/201212/175000.html SQL标识列的查询 1.判段一个表是否具有标识列 www.2cto.com 可 ...
- phantomjs 抓取房产信息
抓取https://sf.taobao.com/item_list.htm信息 driver=webdriver.PhantomJS(service_args=['--ssl-protocol=any ...
- Elastic修改副本数量
分片的个数在创建之后是无法再增加和减少的,除非你另外建一个索引库,而副本是可以在运行的时候,动态增加和减少.因此,在创建索引库时,规划好分片(Shard)是非常重要的,而在插入大量数据时可以先将副本书 ...
- bottle+cherrypy快速开发web服务
我目前用得最顺手的python web框架是bottle,简单方便. bottle有一个开发用的http服务器,效率不高,单线程,阻塞. 所以,得找个别的服务器来部署. 根据bottle官方的文档,发 ...
- PAAS云服务平台
云计算是一种可以方便.按需从网络訪问的.可配置的.共享的资源池(如网络.server.存储.应用程序和服务)模型,且仅仅需最少的管理(服务提供方交互)就可以高速供应和公布该模型. 云计算平台的核心部分 ...
- MP3中设置播放顺序的软件《闪存式MP3伴侣》
给姥爷买了一个插卡音箱,里面拷贝了几百段评书,每一段评书都是一个mp3文件,虽然插卡音箱会自动一个文件一个文件自动播放,可是比较郁闷的是评书的播放顺序完全是乱的,毫无规律可寻,本来我的mp3文件的文件 ...
- OOP Class具体解释
对象[编辑] 对象(Object)是类的实例.比如."狗"这个类列举狗的特点,从而使这个类定义了世界上全部的狗. 而莱丝这个对象则是一条详细的狗,它的属性也是详细的.狗有皮毛颜色. ...
- Python 入门demo第二篇
循环执行逻辑 #-*- coding: UTF-8 -*- import time import urllib2 def task(i): urlstr='http://baidu.com' html ...
- 【服务器时间修改为东八区】包括Apache2和mysql
1.服务器Apache时间修改,可通过修改php.ini进行修改 所以就深入了解了一下, 发现Apache(PHP)的服务器时间时区默认为UTC(Coordinated UniversalTime 世 ...