文章总数25祭+莫队略解
莫队,啥东东?
就是“排序巧妙优化复杂度,带来NOIP前的最后一丝宁静。几个活蹦乱跳的指针的跳跃次数,决定着莫队算法的优劣……”
所以,莫队几乎可以解决一切区间问题
比如
这道题
哈哈
其实是一道莫队入门题
我们先来想离线算法
如图:

文章总数25祭+莫队略解那么…
我们如何从第一次询问转移到第二次询问呐?
很简单
我们定两个指针:l和r
文章总数25祭+莫队略解
然后,就有好玩的事发生了!
两个区间的转移:
事实上是L指针往左/右移,R指针往左/右移
转移增么写?
定义一个数组happen[i]表示当前区间数字i出现的次数
则可以轻易地转移happen了。
但是题目不仅如此,还要我们计算它们的平方和
所以:
当每次移指针时,ans减去happen[last]2 加上happen[now]2 即可
恭喜你已经YY出了原始莫队!
但是复杂度仍是不堪入目
要是跳的太远,会还原成O(nm)级别的(暴力)
所以莫队的精髓来了:排序
怎么排?
要用到分块优化
定义b[i]表示第i个数所属块
定义u表示块数
u=sqrt(n)
b[i]=(i/u)+1
然后排序
如果两个区间的l在同块内,r小的排前面。
否则l小的排前面
为什么不以l为第一关键字,r为第二关键字排序内?
我也不知道
举个例子:
1 2
2 100000
3 3
自己体会一下即可
例题:
HH的项链
模板!
但是很遗憾,莫队只有80分
80pts:

#include<bits/stdc++.h>
using namespace std;
const int N=1000005; 
struct node{
    int l,r;
    int Rk;
    int ans;
}s[N];
int n,m;
int col[N];
int u;
int b[N];
int happen[5000005]={0};
int ans=0;
int l,r;
bool cmp(node x,node y){
    if(b[x.l]==b[y.l]) return x.r<y.r;
    return x.l<y.l;
}
bool kmp(node x,node y){
    return x.Rk<y.Rk;
}
int main(){
    scanf("%d",&n);
    u=sqrt(n);
    for(register int i=1;i<=n;i++) b[i]=(i/u)+1;//计算所属块 
    for(register int i=1;i<=n;i++) scanf("%d",&col[i]);
    scanf("%d",&m);
    for(register int i=1;i<=m;i++){
        scanf("%d%d",&s[i].l,&s[i].r);
        s[i].Rk=i;
    }
    sort(s+1,s+m+1,cmp);
    for(register int i=1;i<=m;i++){
        if(i==1){
            for(register int j=s[i].l;j<=s[i].r;j++){
                happen[col[j]]++;
                if(happen[col[j]]==1) ans++;
            }
            s[i].ans=ans;
        }
        else{
            while(l<s[i].l){
                l++;
                happen[col[l-1]]--;
                if(happen[col[l-1]]==0) ans--;
            }
            while(l>s[i].l){
                l--;
                happen[col[l]]++;
                if(happen[col[l]]==1) ans++;
            }
            while(r<s[i].r){
                r++;
                happen[col[r]]++;
                if(happen[col[r]]==1) ans++;
            }
            while(r>s[i].r){
                r--;
                happen[col[r+1]]--;
                if(happen[col[r+1]]==0) ans--;
            }
            s[i].ans=ans;
        }
        l=s[i].l,r=s[i].r;
    }
    sort(s+1,s+m+1,kmp);
    for(register int i=1;i<=m;i++){
        printf("%d\n",s[i].ans);
    }
    return 0;
} 

海星
P4137 Rmq Problem / mex
简单?
但是:
90:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000005;
struct node{
    int l,r;
    int ans;
    int Rk;
}s[N];
int n,m;
int col[N];
int b[N];
int u;
int happen[N]={0};
int l,r;
int ans=0;
bool cmp(node x,node y){
    if(b[x.l]==b[y.l]) return x.r<y.r;
    return x.l<y.l;
}
bool kmp(node x,node y){
    return x.Rk<y.Rk;
}
int main(){
    scanf("%d%d",&n,&m);
    u=sqrt(n);
    for(int i=1;i<=n;i++) b[i]=(i/u)+1;
    for(int i=1;i<=n;i++){
        scanf("%d",&col[i]);
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&s[i].l,&s[i].r);
        s[i].Rk=i;
    }
    sort(s+1,s+m+1,cmp);
    for(int i=1;i<=m;i++){
        if(i==1){
            for(int j=s[i].l;j<=s[i].r;j++){
                happen[col[j]]++;
                if(happen[col[j]]==1){
                    while(happen[ans]) ans++;
                }
            }
            l=s[i].l,r=s[i].r;
        }
        else{
            while(l<s[i].l){
                l++;
                happen[col[l-1]]--;
                if(happen[col[l-1]]==0&&col[l-1]<ans) ans=min(ans,col[l-1]);
            }
            while(l>s[i].l){
                l--;
                happen[col[l]]++;
                int ii=ans;
                while(happen[ii]) ii++;
                ans=ii;
            }
            while(r<s[i].r){
                r++;
                happen[col[r]]++;
                int ii=ans;
                while(happen[ii]) ii++;
                ans=ii;
            }
            while(r>s[i].r){
                r--;
                happen[col[r+1]]--;
                if(happen[col[r+1]]==0&&col[r+1]<ans) ans=min(ans,col[r+1]);
            }
        }
        s[i].ans=ans;
    }
    sort(s+1,s+m+1,kmp);
    for(int i=1;i<=m;i++){
        printf("%d\n",s[i].ans);
    }
    return 0;
} 

100

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000005;
struct node{
    int l,r;
    int ans;
    int Rk;
}s[N];
int n,m;
int col[N];
int b[N];
int u;
int happen[N]={0};
int l,r;
int ans=0;
bool cmp(node x,node y){
    if(b[x.l]==b[y.l]) return x.r<y.r;
    return x.l<y.l;
}
bool kmp(node x,node y){
    return x.Rk<y.Rk;
}
int main(){
    scanf("%d%d",&n,&m);
    u=sqrt(n);
    for(int i=1;i<=n;i++) b[i]=(i/u)+1;
    for(int i=1;i<=n;i++){
        scanf("%d",&col[i]);
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&s[i].l,&s[i].r);
        s[i].Rk=i;
    }
    sort(s+1,s+m+1,cmp);
    for(int i=1;i<=m;i++){
        if(i==1){
            for(int j=s[i].l;j<=s[i].r;j++){
                happen[col[j]]++;
                if(happen[col[j]]==1){
                    while(happen[ans]) ans++;
                }
            }
            l=s[i].l,r=s[i].r;
        }
        else{
            while(l<s[i].l){
                l++;
                happen[col[l-1]]--;
                if(happen[col[l-1]]==0&&col[l-1]<ans) ans=min(ans,col[l-1]);
            }
            while(l>s[i].l){
                l--;
                happen[col[l]]++;
                if(col[l]==ans) while(happen[ans]) ans++;
            }
            while(r<s[i].r){
                r++;
                happen[col[r]]++;
                if(col[r]==ans) while(happen[ans]) ans++;
            }
            while(r>s[i].r){
                r--;
                happen[col[r+1]]--;
                if(happen[col[r+1]]==0&&col[r+1]<ans) ans=min(ans,col[r+1]);
            }
        }
        s[i].ans=ans;
    }
    sort(s+1,s+m+1,kmp);
    for(int i=1;i<=m;i++){
        printf("%d\n",s[i].ans);
    }
    return 0;
}  

至为什么要加if(col[l]==ans)我至今不明
我太弱了,以至于不会带修莫队
但是:

THE END

相关文章:

  • 2020-01-20
  • 2018-12-19
  • 2020-10-12
  • 2019-11-01
  • 2022-01-02
  • 2020-10-09
  • 2021-08-06
猜你喜欢
  • 2020-03-16
  • 2021-11-15
  • 2019-06-25
  • 2021-08-14
  • 2019-02-17
  • 2021-11-18
  • 2021-11-03
  • 2021-01-12
相关资源
相似解决方案