题解:P2075 区间 LIS
首先,求一个序列
这可以解释为,对
现在我们考虑区间询问怎么做,设
既然如此,我们要求出
现在只需要考虑:在
我们先来考虑
以此类推,读者想必已经看出:
q[v]=r+1,now=0
for(int i=v+1;i<=n;i++)if(q[i]>now)swap(q[i],now)
此时,如果你做过回转寿司,那么这个题的解法已经呼之欲出了。
考虑到这部分也并不算简单,我在这里也详细描述一下这部分是怎么做的。
我们先考虑一个简单的情形:每次操作,我们都是完整地枚举
现在我们的
我们不妨先来考虑第一个元素
综上,我们得到一个
#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define fi first
#define se second
using namespace std;
#define gc getchar
inline int read(){
int x=0,f=1;char c=getchar();
for(;(c<'0'||c>'9');c=getchar()){if(c=='-')f=-1;}
for(;(c>='0'&&c<='9');c=getchar())x=x*10+(c&15);
return x*f;
}
template<typename T>void cmax(T &x,T v){x=max(x,v);}
template<typename T>void cmin(T &x,T v){x=min(x,v);}
const int N=1e5+5;
int a[N],q[N],n,ans[N],m;
vector<pair<int,int> >ques[N];
struct BIT{
int c[N];
int lowbit(int x){return x&(-x);}
void add(int x,int v){x++;for(int i=x;i<=n+1;i+=lowbit(i))c[i]+=v;}
int sum(int x){int res=0;for(int i=x+1;i;i-=lowbit(i))res+=c[i];return res;}
}T;
const int B=250;
const int NB=N/B+5;
priority_queue<int>P[NB],Q[NB];
int L[NB],R[NB],bl[N];
void rebuild(int p){
if(Q[p].size()==0)return ;
int l=L[p],r=R[p];
for(int i=l;i<=r;i++)if(q[i]>-Q[p].top()){
int cur=-Q[p].top();
Q[p].pop(),Q[p].push(-q[i]),q[i]=cur;
}
priority_queue<int>().swap(Q[p]);
}
signed main(void){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=m;i++){
int l=read(),r=read();
ques[r].emplace_back(mk(l,i));
}
int S=sqrt(n);memset(L,63,sizeof(L));
for(int i=1;i<=n;i++)bl[i]=(i-1)/S+1,cmin(L[bl[i]],i),cmax(R[bl[i]],i);
for(int i=1;i<=bl[n];i++)for(int j=L[i];j<=R[i];j++)P[i].push(0);
T.add(0,n);
for(int i=1;i<=n;i++){
int v=a[i],now=0;
if(v+1<=n){
int p=bl[v+1];rebuild(p);
for(int j=v+1;j<=R[p];j++)if(q[j]>now)swap(now,q[j]);
priority_queue<int>().swap(P[p]);
for(int j=L[p];j<=R[p];j++)P[p].push(q[j]);
for(int j=p+1;j<=bl[n];j++)if(P[j].top()>now){
int cur=P[j].top();
P[j].pop(),P[j].push(now),Q[j].push(-now),now=cur;
}
T.add(now,-1),T.add(0,1);
}
rebuild(bl[v]);
T.add(q[v],-1),q[v]=i,T.add(q[v],1);
priority_queue<int>().swap(P[bl[v]]);
for(int j=L[bl[v]];j<=R[bl[v]];j++)P[bl[v]].push(q[j]);
for(auto [l,id]:ques[i])ans[id]=T.sum(n)-T.sum(l-1);
}
for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
return 0;
}