• 莫队入门例题


    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;
    }
    
  • 相关阅读:
    随机生成三十个二年级的加减乘除法的题目代码
    学习进度表_四周
    返回一个整数数组中最大子数组的和1
    学习进度表_三周
    四则运算4
    构建之法读书笔记2
    学习进度表_二周
    四则运算3
    四则运算2
    单元测试
  • 原文地址:https://www.cnblogs.com/OvOq/p/14719495.html
Copyright © 2020-2023  润新知