莫队入门例题

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;
}
posted @ 2021-04-29 20:12  OvO1  阅读(67)  评论(0编辑  收藏  举报