蒟蒻无聊之一
Posted wzxbeliever
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蒟蒻无聊之一相关的知识,希望对你有一定的参考价值。
一道很简单的练手题目
https://loj.ac/problem/10121#submit_code
题目大意:
多次询问区间的完美序列;(完美序列定义为一段连续序列中各个数字都不同)
求多个区间最长完美序列(不修改)
分析:
静态查询:last数组,求最大?dp数组
(动态查询估计就要莫队了吧)
last[a[i]]表示数a[i]的上一次出现的位置
dp[i]表示以第i位结尾的最长完美序列的起始位置的max
就有:dp[i]=max(dp[i-1],last[a[i]]+1)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!这个dp数组是关键
最后查询用st表预处理(i-dp[i]+1)就是每个序列的长度
因为last数组是单调递增的,所以用二分就可以解决一段区间的前段不在该区间内的情况
能不手写二分就不,边界范围太难掌控了
code by wzxbeliever
#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) x&(-x)
#define il inline
#define ri register int
using namespace std;
const int maxn=2e5+5;
const int maxx=1e6;
int lg[maxn],last[(maxx<<1)+5],st[maxn][20],s[maxn],f[maxn];
int n,m;
il void init(){
lg[0]=-1;
for(ri i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
for(ri j=1;(1<<j)<=n;j++)
for(ri i=1;i+(1<<j)-1<=n;i++)
st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
return;
}
il int askmax(int L,int R){
if(L>R)return 0;
int k=lg[R-L+1];
return max(st[L][k],st[R-(1<<k)+1][k]);
}
int main(){
scanf("%d%d",&n,&m);
for(ri i=1,x;i<=n;i++){
scanf("%d",&x);
s[i]=max(s[i-1],last[x+maxx]+1);
f[i]=i-s[i]+1;
st[i][0]=f[i];
last[x+maxx]=i;
}
init();
for(ri i=1,L,R;i<=m;i++){
scanf("%d%d",&L,&R);L++,R++;
int pos=lower_bound(s+1+L,s+1+R,L)-s-1;
//cout<<"pos="<<pos<<endl;
printf("%d
",max(pos-L+1,askmax(pos+1,R)));
}
return 0;
}
以上是关于蒟蒻无聊之一的主要内容,如果未能解决你的问题,请参考以下文章