昨晚重新打的莫队今天调试出来了
//这个是这一次的写法
//首先的话就是必须要找到的是这个区间内的贝壳的个数
//使用一个链表对于每一个的话都是存储他的上一个最近的地点
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=5e4+40,M=2e5+40,K=1e6+40;
int col[N];
int n,m,len,ans[M],res;//记得是m的存在
int l,r;
int get(int x)
{
return x/len;
}
struct node{
int l,r,id;
bool operator<(const node& a)const
{
int x=get(l),y=get(a.l);
if(x!=y)
{
return x<y;
}
return r<a.r;
}
}q[M];
int num[K];
void del(int x,int k)
{
num[k]--;
if(!num[k]) res--;
}//这个是最近的
void add(int x,int k)
{
if(!num[k]) res++;
num[k]++;
}//这个是删除
void show()
{
cout<<res<<" "<<l<<" "<<r<<endl;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&col[i]);
// col[i]++;
}
col[0]=1e6+30;//如果第一个的编号是0的话是会有问题的啊
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
len=sqrt(n);
sort(q,q+m);
int x,y;
for(int i=0;i<m;i++){
x=q[i].l,y=q[i].r;
while(l>x){
--l;
add(l,col[l]);
}
while(r<y){
++r;
add(r,col[r]);
}
while(r>y&&l<r){
del(r,col[r]);
r--;
}
while(l<x&&l<r){
del(l,col[l]);
l++;
}
ans[q[i].id]=res;
}
for(int i=0;i<m;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}
带修改的莫队
最优复杂下的len的计算需要学习一下
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5e4+20,M=2e5+30,S=1e6+20;
int w[N],cnt[S],ans[M],len;
int get(int x)
{
return x/len;
}
struct node{
int l,r,id;
bool operator<(node a)
{
if(get(l)!=get(a.l))
{
return get(l)<get(a.l);
}
return r<a.r;
}
}q[M];
void add(int x,int& res)
{
if(!cnt[w[x]])
{
res++;
}
cnt[w[x]]++;
}
void del(int x,int& res)
{
cnt[w[x]]--;
if(!cnt[w[x]]) res--;
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i];//放在外面的时候可以节省空间
}
int m;
cin>>m;
len=sqrt((double) n);//区间的是除以m
for(int i=1;i<=m;i++)
{
cin>>q[i].l>>q[i].r;
q[i].id=i;
}
sort(q+1,q+m+1);
int res=0;
for(int k=1,i=0,j=1;k<=m;k++)
{
int id=q[k].id,l=q[k].l,r=q[k].r;
while(i<r)
{
i++;//对于这一个是有顺序的
add(i,res);
}
while(i>r)
{
del(i,res);
i--;
}//减的时候是先减在加
while(j>l)
{
j--;//对于左区间的话与右区间的不一样
add(j,res);
}
while(j<l)
{
del(j,res);
j++;
}//注意一下两边的改变
ans[id]=res;
}//注意边界问题
for(int i=1;i<=m;i++)
cout<<ans[i]<<endl;
return 0;
}
回滚莫队
//调试的时候造了一组样例发现应该是初始化错了,但是一直找不到哪里忘记初始化了,最后才想起来每一次重新找新的块的起点的时候res需要进行清零而不是全局变量
//好像还有一个普通莫队的做法用的是记录出前驱和后继的在看看
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+40;
int a[N],col[N];
int b[N],st[N],clear[N],ans[N],ma[N];
int cs;
vector<int>s;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
struct node{
int l,r,i;
bool operator<(const node& a)const {
return (b[l]!=b[a.l])?(b[l]<b[a.l]):(r<a.r);
}
}q[N];
int find(int x)
{
return (lower_bound(s.begin(),s.end(),x)-s.begin())+1;
}
int cal(int l,int r)
{
int last[N],ans=0;
for(int i=l;i<=r;i++) last[col[i]]=0;
for(int i=l;i<=r;i++){
if(!last[col[i]]){
last[col[i]]=i;
}else {
ans=max(ans,i-last[col[i]]);
}
}
return ans;
}
int main()
{
int n,m;
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
s.push_back(a[i]);
}
sort(s.begin(),s.end());
s.erase(unique(s.begin(),s.end()),s.end());
int len=sqrt(s.size());
for(int i=1;i<=n;i++)
{
b[i]=(i-1)/len+1;//这个才是你们的分块
}
for(int i=1;i<=n;i++)
{
col[i]=find(a[i]);
}
m=read();
for(int i=0;i<m;i++)
{
q[i].l=read(),q[i].r=read();
q[i].i=i;
}
sort(q,q+m);
int bn=b[n];
for(int i=0,j=1;j<=bn;j++)
{
//开始进行一个枚举
int br=min(j*len,n),r=br,l,res=0;//重新计算啊
cs=0;//清楚标记
for(;b[q[i].l]==j&&i<m;i++)
{
//然后的话开始枚举如果是同一个内部的话
if(b[q[i].r]==j)
{
ans[q[i].i]=cal(q[i].l,q[i].r);
continue;
}
l=br+1;
//然后的话就是开始了新的做法了啊
while(r<q[i].r){
//开始进行添加啊
r++;
if(!st[col[r]]){
ma[col[r]]=st[col[r]]=r;
clear[cs++]=col[r];
//还有一个的话是记录出最大的编号是多少就好了
}else {
res=max(res,r-st[col[r]]);
ma[col[r]]=max(ma[col[r]],r);
}
}
int tm=res;
while(l>q[i].l)
{
--l;
if(!st[col[l]]) {
ma[col[l]]=l;
st[col[l]]=l;
}else {
res=max(res,ma[col[l]]-l);
}
}
ans[q[i].i]=res;
while(l<=br)
{
if(ma[col[l]]==l)
{
st[col[l]]=ma[col[l]]=0;
}//删除标志
l++;
}
res=tm;
//然后的话就要开始进行一个删除了
}
for(int i=0;i<cs;i++)
{
ma[clear[i]]=st[clear[i]]=0;
}
}
for(int i=0;i<m;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}
背完50个6级词汇了