莫队入门例题
P3901 数列找不同
思路:
用一个桶直接维护每个数出现的次数和当前区间里不同数的个数,如果不同数的个数等于区间长度,说明该区间的数互不相同。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
int n,m,a[maxn];
struct node{
int l,r,id;
}q[maxn];
int len,ans[maxn],res,cnt[maxn];
bool cmp(node a,node b){
if(a.l/len==b.l/len) return a.r<b.r;
return a.l/len<b.l/len;
}
void del(int x){
cnt[a[x]]--;
if(cnt[a[x]]==0) res--;
}
void add(int x){
cnt[a[x]]++;
if(cnt[a[x]]==1) res++;
}
int main(){
cin>>n>>m;
len=sqrt(n);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
cin>>q[i].l>>q[i].r;q[i].id=i;
}
sort(q+1,q+1+m,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++){
int ql=q[i].l,qr=q[i].r,qid=q[i].id;
while(l<ql){
del(l);l++;
}
while(l>ql){
l--;add(l);
}
while(r>qr){
del(r);r--;
}
while(r<qr){
r++;add(r);
}
if(res==qr-ql+1) ans[qid]=1;
}
for(int i=1;i<=m;i++){
if(ans[i]) puts("Yes");
else puts("No");
}
return 0;
}
P2709 小B的询问
思路:
考虑每次指针移动对答案的贡献。
\[(c+1)^{2}-c^{2}=c*2-1
\]
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
int a[maxn],n,m,k;
struct node{
int l,r,id;
}q[maxn];
int len,ans[maxn],res,cnt[maxn];
bool cmp(node a,node b){
if(a.l/len==b.l/len) return a.r<b.r;
return a.l/len<b.l/len;
}
void del(int x){
res-=2*cnt[a[x]]-1;
cnt[a[x]]--;
}
void add(int x){
res+=2*cnt[a[x]]+1;
cnt[a[x]]++;
}
int main(){
cin>>n>>m>>k;
len=sqrt(n);
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>q[i].l>>q[i].r;q[i].id=i;
}
sort(q+1,q+1+m,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++){
int ql=q[i].l,qr=q[i].r,qid=q[i].id;
while(l<ql){
del(l);l++;
}
while(l>ql){
l--;add(l);
}
while(r>qr){
del(r);r--;
}
while(r<qr){
r++;add(r);
}
ans[qid]=res;
}
for(int i=1;i<=m;i++)
cout<<ans[i]<<endl;
return 0;
}
CF86D Powerful array
思路:
还是考虑当某个数增加1或减少1时对答案的影响
\[(cnt_{i}+1)^{2}*i-cnt_{i}^{2}*i=i*(2*cnt_{i}+1)
\]
减少1也同理。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+70;
typedef long long ll;
struct node{
ll l,r,id;
}q[maxn];
ll n,m,a[maxn],res,len;
ll cnt[maxn],ans[maxn];
bool cmp(node a,node b){
if(a.l/len==b.l/len) return a.r<b.r;
return a.l/len<b.l/len;
}
void add(int x){
res+=2*cnt[a[x]]*a[x]+a[x];
cnt[a[x]]++;
}
void del(int x){
res-=2*cnt[a[x]]*a[x]-a[x];
cnt[a[x]]--;
}
int main(){
cin>>n>>m;
len=sqrt(n);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
cin>>q[i].l>>q[i].r;q[i].id=i;
}
sort(q+1,q+1+m,cmp);
ll l=1,r=0;
for(int i=1;i<=m;i++){
int ql=q[i].l,qr=q[i].r;
while(l<ql){
del(l);l++;
}
while(l>ql){
l--;add(l);
}
while(r>qr){
del(r);r--;
}
while(r<qr){
r++;add(r);
}
ans[q[i].id]=res;
}
for(int i=1;i<=m;i++){
cout<<ans[i]<<endl;
}
return 0;
}