题意: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. python参考手册--第4、5、6、7章

    1.zip zip(s,t):将序列组合为一个元组序列[(s[0],t[0]), (s[1],t[1]), (s[2],t[2]), (s[3],t[3]),...] >>> s = ...

  2. HDU4714+三分

    题意:给定N个点,每个点有初始位置和初始速度. 问:在哪个时刻 使得所有的点的最大距离值最小. 分析:一开始枚举两两之间的最大值,然后在最大值中求一个最小值...(WA:题意严重理解不清..) 由两点 ...

  3. Android UI-开源框架ImageLoader的完美例子

    Android开源框架ImageLoader的完美例子 2013年8月19日开源框架之Universal_Image_Loader学习 很多人都在讨论如何让图片能在异步加载更加流畅,可以显示大量图片, ...

  4. dynamic_cast 用法

    dynamic_cast < type-id > ( expression ) 该运算符把expression转换成type-id类型的对象.Type-id必须是类的指针.类的引用或者vo ...

  5. 【HDOJ】4347 The Closest M Points

    居然是KD解. /* 4347 */ #include <iostream> #include <sstream> #include <string> #inclu ...

  6. Android-xUtils框架介绍(一)

    Android基于快速开发的一个框架——xUtils,它是在aFinal基础上进行重构和扩展的框架,相比aFinal有很大的改善.同时,如果如果你的应用是基于网络的,那么只要处理得当,它会让你彻底的摆 ...

  7. Eclipse导入项目

    导入Eclipse项目 File->Import...->Existing Projects into Workspace->Next->Browse...->Finis ...

  8. .net 测试工具类

    fluentassertions QuickStart  (替换Assert ) https://github.com/dennisdoomen/fluentassertions/wiki   Moq ...

  9. JAVA并行框架学习之ForkJoin

    当硬件处理能力不能按照摩尔定律垂直发展的时候,选择了水平发展,多核处理器已经广泛应用.未来随着技术的进一步发展,可能出现成百上千个处理核心,但现有的程序运行在多核心处理器上并不能得到较大性能的提升,主 ...

  10. bzoj1293: [SCOI2009]生日礼物

    单调队列 用一个堆维护目前每个颜色在里面的点,每回取出队首点,并更新答案.一旦哪个颜色的点都被用完,跳出循环. #include<cstdio> #include<algorithm ...