题意:
分析:
啊啊啊啊我发明的算法居然以前有过。。。。https://blog.csdn.net/qq_34454069/article/details/80184286
方法其实很简单。。。首先,把所有未加入的点放在一个双向链表里。
然后,每次插入一个值,就相当于把这个点从双向链表中删除。每次删除的时候,统计一下其左侧和右侧的,已经从链表中删去(即已经插入的)点的个数即可。
然而,问题来了,如果做莫队的话。。有个小问题:插入值还好,但如果要删除一个值,你就会把原来某个连续的区间,划分为两部分。然而这样一来,你无法确定剩下的所有连续区间的最大长度。
所以,不能删除的莫队?就是我之前讲的那个算法(学名叫回滚莫队)。
排序方式还是一样的,只不过这里对每个左端点在一个块内的分别处理:
首先,先清空之前的状态。
然后,右端点向右拓展直到某个询问的右端点。
现在保存所有当前答案。然后再依次插入左区间的点
得到答案后,再依次撤回操作(具体实现是通过栈暴力存储每次修改的地方,参见代码)
再做下一次操作。
复杂度
O
(
N
N
)
O(N\sqrt N)
O(NN)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#define MAXN 100010
#define SF scanf
#define PF printf
using namespace std;
typedef pair<int,int> pii;
int a[MAXN],blo[MAXN];
int ans[MAXN],ansx;
struct node{
int l,r,id;
bool operator <(const node &a) const{
if(blo[l]!=blo[a.l])
return blo[l]<blo[a.l];
return r<a.r;
}
}q[MAXN];
int lp[MAXN],rp[MAXN];
struct chag{
int l,orgl;
int r,orgr;
chag () {}
chag (int l1,int ol1,int r1,int or1):l(l1),orgl(ol1),r(r1),orgr(or1) {}
};
stack<chag> s;
void add(int x,bool flag){
int sizl=x-lp[x]-1;
int sizr=rp[x]-x-1;
ansx=max(ansx,sizl+sizr+1);
if(flag)
s.push(chag(lp[x],rp[lp[x]],rp[x],lp[rp[x]]));
rp[lp[x]]=rp[x];
lp[rp[x]]=lp[x];
}
void restore(){
while(!s.empty()){
int l=s.top().l;
int r=s.top().r;
int orgl=s.top().orgl;
int orgr=s.top().orgr;
rp[l]=orgl;
lp[r]=orgr;
s.pop();
}
}
int n,m;
void solve(int lasx,int L,int R){
int las=lasx-1;
for(int i=1;i<=n;i++){
lp[i]=i-1;
rp[i]=i+1;
}
ansx=0;
while(q[L].r<lasx&&L<=R){
for(int i=q[L].l;i<=q[L].r;i++)
add(a[i],1);
ans[q[L].id]=ansx;
restore();
ansx=0;
L++;
}
for(int i=L;i<=R;i++){
while(las<q[i].r)
add(a[++las],0);
int pans=ansx;
for(int j=lasx-1;j>=q[i].l;j--)
add(a[j],1);
ans[q[i].id]=ansx;
restore();
ansx=pans;
}
}
int main(){
freopen("ants.in","r",stdin);
freopen("ants.out","w",stdout);
SF("%d%d",&n,&m);
for(int i=1;i<=n;i++)
SF("%d",&a[i]);
for(int i=1;i<=m;i++){
SF("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
int BASE=int(sqrt(n));
for(int i=1;i<=n;i++)
blo[i]=i/BASE+1;
sort(q+1,q+1+m);
int las=1;
for(int i=2;i<=m;i++)
if(blo[q[i].l]!=blo[q[i-1].l]){
solve(blo[q[i-1].l]*BASE,las,i-1);
las=i;
}
solve(blo[q[las].l]*BASE,las,m);
for(int i=1;i<=m;i++)
PF("%d\n",ans[i]);
}