题意:N个数,M个询问,每个询问为一个区间,求区间最长连续子序列,要求每个数都不同(perfect sequence,简称PS)。

题解:很容易求出以每个数为结尾的ps,也就是求区间的最大值。有一个不同就是长度可能会超出询问范围,所以先对PS的首位置二分,然后RMQ。注意一点,序列有可能出现负数,所以先加最大值变为正数。其实也不算变形,挺裸的……

这题卡线段树,然而我只会线段树,心塞……

代码(树状数组):

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = ; int a[N], pos[N], len[N], nt[N]; #define lowbit(x) ((x)&(-x))
int idx[N]; void init(int n)
{
for(int i=;i<=n;i++) {
idx[i] = len[i];
for(int j=;j<lowbit(i);j<<=){
idx[i]=max(idx[i],idx[i-j]);
}
}
} int query(int l, int r)
{
int ans=len[r];
while(true) {
ans=max(ans,len[r]);
if(r==l) break;
for(r-=;r-l>=lowbit(r);r-=lowbit(r)){
ans=max(ans,idx[r]);
}
}
return ans;
} int main()
{
int n, m;
while (~scanf("%d%d", &n, &m)) {
for (int i = ; i <= n; ++i) {
scanf("%d", &a[i]);
a[i] += ;
}
memset(pos, , sizeof pos);
nt[] = ;
for (int i = ; i <= n; ++i) {
nt[i] = max(nt[i-], pos[a[i]]+);//nt[i]以i为结尾的最长子序列的首端
len[i] = i-nt[i]+;
pos[a[i]] = i;
}
init(n); while (m--) {
int l, r;
scanf("%d%d", &l, &r); l++, r++;
int p = upper_bound(nt+, nt++n, l) - nt;
int ans = ;
if (p > r) {
printf("%d\n", r-l+);
continue;
}
if (p > l) ans = p-l;
ans = max(ans, query(p, r));
printf("%d\n", ans);
}
}
return ;
}

代码(ST算法):

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = ; int a[N], pos[N], len[N], nt[N];
int f[N][]; void init(int n)
{
// f[i,j]表示[i,i+2^j-1]区间最大值
// f[i,j]=max(d[i,j-1], d[i+2^(j-1),j-1])
for (int i = ; i <= n; ++i) f[i][] = len[i];
for (int j = ; (<<j) <= n; ++j)
for (int i = ; i+j- <= n; ++i)
f[i][j] = max(f[i][j-], f[i+(<<j-)][j-]);
} int query(int l, int r)
{
int k = ;
while ((<<k+ <= r-l+)) ++k;
return max(f[l][k], f[r-(<<k)+][k]);
} int main()
{
int n, m;
while (~scanf("%d%d", &n, &m)) {
for (int i = ; i <= n; ++i) {
scanf("%d", &a[i]);
a[i] += ;
}
memset(pos, , sizeof pos);
nt[] = ;
for (int i = ; i <= n; ++i) {
nt[i] = max(nt[i-], pos[a[i]]+);//nt[i]以i为结尾的最长子序列的首端
len[i] = i-nt[i]+;
pos[a[i]] = i;
}
init(n); while (m--) {
int l, r;
scanf("%d%d", &l, &r); l++, r++;
int p = upper_bound(nt+, nt++n, l) - nt;
int ans = ;
if (p > r) {
printf("%d\n", r-l+);
continue;
}
if (p > l) ans = p-l;
ans = max(ans, query(p, r));
printf("%d\n", ans);
}
}
return ;
}

还有一种网上流传的算法,类似kmp。想法很巧妙,但是最坏复杂度貌似是O(n^2),不过也能A这道题。而且速度不必上面慢。数据水吧~

nt[i]记录想要字串中含有a[(i+1)-pos[i+1]]的最大位置。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = ; int a[N], pos[N], len[N], nt[N]; int main()
{
int n, m;
while (~scanf("%d%d", &n, &m)) {
for (int i = ; i <= n; ++i) {
scanf("%d", a+i);
a[i] += ;
}
memset(pos, , sizeof pos);
len[] = ; nt[] = ;
for (int i = ; i <= n; ++i) {
if (len[i-]+ <= i-pos[a[i]]) {
len[i] = len[i-]+;
nt[i] = nt[i-];
} else {
len[i] = i-pos[a[i]];
nt[i] = i-;
}
pos[ a[i] ] = i;
//printf("%d %d %d\n", len[i], nt[i], pos[a[i]]);
}
while (m--) {
int l, r;
scanf("%d%d", &l, &r); l++, r++;
int res = len[r];
if (res >= r-l+) {
printf("%d\n", r-l+);
continue;
}
while (nt[r] > ) {
r = nt[r];
res = max(res, min(len[r], r-l+));
if (res >= r-l+) {
break;
}
}
printf("%d\n", res);
}
}
return ;
}

POJ 3419 Difference Is Beautiful(RMQ变形)的更多相关文章

  1. POJ 3419 Difference Is Beautiful(RMQ+二分 或者 模拟)

    Difference Is Beautiful Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%lld & %l ...

  2. POJ 3419 Difference Is Beautiful (DP + 二分 + rmq)

    题意:给n个数(n<=200000),每个数的绝对值不超过(10^6),有m个查询(m<=200000),每次查询区间[a,b]中连续的没有相同数的的最大长度. 析:由于n太大,无法暴力, ...

  3. POJ 3419 Difference Is Beautiful

    先处理出每一个i位置向左最远能到达的位置L[i].每一次询问,要找到L,R区间中的p位置,p位置左边的L[i]都是小于L的,p位置开始,到R位置,L[i]都大于等于L,对于前者,最大值为p-L,后者求 ...

  4. poj 3368 Frequent values(RMQ)

    题目:http://poj.org/problem?id=3368 题意:给定n个数,顺序为非下降,询问某个区间内的数出现最多的数的 出现次数.. 大白书上的 例题..算是RMQ变形了, 对 原数组重 ...

  5. POJ 3635 - Full Tank? - [最短路变形][手写二叉堆优化Dijkstra][配对堆优化Dijkstra]

    题目链接:http://poj.org/problem?id=3635 题意题解等均参考:POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]. 一些口胡: ...

  6. POJ 2019 Cornfields [二维RMQ]

    题目传送门 Cornfields Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7963   Accepted: 3822 ...

  7. POJ 1696 - Space Ant 凸包的变形

    Technorati Tags: POJ,计算几何,凸包 初学计算几何,引入polygon后的第一个挑战--凸包 此题可用凸包算法做,只要把压入凸包的点从原集合中排除即可,最终形成图形为螺旋线. 关于 ...

  8. poj 3264 Balanced Lineup(RMQ裸题)

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 43168   Accepted: 20276 ...

  9. POJ 3264 Balanced Lineup(RMQ)

    点我看题目 题意 :N头奶牛,Q次询问,然后给你每一头奶牛的身高,每一次询问都给你两个数,x y,代表着从x位置上的奶牛到y位置上的奶牛身高最高的和最矮的相差多少. 思路 : 刚好符合RMQ的那个求区 ...

随机推荐

  1. Ubuntu环境下手动配置Java环境

    /×××××××××××××××××××××××××××××××××××××××××/ Author:xxx0624 HomePage:http://www.cnblogs.com/xxx0624/ ...

  2. ibatis的there is no statement named xxx in this SqlMap

    报错情况如下: com.ibatis.sqlmap.client.SqlMapException: There is no statement named Control.insert-control ...

  3. cocos2dx Sprite setBlendFunc 使用颜色混合:加算,减算

    说明: 图片的混色是游戏的特效的特破口,应用的好,可以大量减少图片的使用量,有专门的介绍资料... setBlendFunc  相关参数,有多种组合方式,需要经验的积累 http://blog.csd ...

  4. AppStore 沙箱环境的测试流程

    1:请确保你打得版本是 沙箱环境的版本 2:请确保的手机序列号已经加入沙箱环境3:请确保你的手机Apple ID 账户已经退出 ------ 如果这些都准备好了,再进行测试吧,不然一堆的未知问题等着你 ...

  5. 这些废弃的 HTML 标签不要用

    HTML 已经发展了多年,现在 W3C 已经发布了 HTML 5.1 的提案推荐标准,一些陈旧废弃的标签已经在后继的标准中逐渐消失.这里为大家列出那些已经被废弃 HTML 标签,看看你是不是还在使用它 ...

  6. Android性能优化之如何避免Overdraw

    什么是Overdraw? Overdraw就是过度绘制,是指在一帧的时间内(16.67ms)像素被绘制了多次,理论上一个像素每次只绘制一次是最优的,但是由于重叠的布局导致一些像素会被多次绘制,而每次绘 ...

  7. border-radius的水平和竖直半径

    通常我们设置border-radius都只区分四个角的, 如border-radius: 1em 2em. 其实每个角的border-radius都由两部分组成, 水平半径和竖直半径. 要设置水平和竖 ...

  8. Oracle中Blob和Clob类型的区别与操作

    Oracle中Blob和Clob类型 1.Oracle中Blob和Clob类型的区别 BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的.其实两个是可以互换的 ...

  9. Windows Embedded Compact 7新特性

    Windows® Embedded Compact 7是Windows Embedded CE的下一代产品,而Windows Embedded CE这款操作系统面向占用资源少的新颖设备.Windows ...

  10. 配置oschina for pc 开发环境

    oschina for pc 是一款用python + pyqt + html + css +js开发的桌面程序,感觉十分强大.python开发快捷, 网页技术绚丽,正是桌面程序需要的. 感谢铂金小鸟 ...