首页 > 其他分享 >莫队学习笔记

莫队学习笔记

时间:2023-12-27 14:34:25浏览次数:22  
标签:int 笔记 学习 bl while && 莫队 getchar

前置知识:分块

莫队是非常好的数据结构,可以离线解决很多序列问题

当对于一个查询\([l,r]\)可以\(O(1)\)转移到\([l-1,r],[l+1,r],[l,r-1],[l,r+1]\)时可以考虑用(普通)莫队

莫队先读入所有的询问,接着离线对于所有询问区间 \([l,r]\) , 用 \(l\) 所在块的编号为第一关键字, \(r\) 为第二关键字从小到大进行排序

inline bool cmp(const blo &a,const blo &b){
	if(bl[a.l]<bl[b.l])return 1;
	if(bl[a.l]>bl[b.l])return 0;
	if(bl[a.l]&1)return a.r<b.r;
	return a.r>b.r;
}

上面的代码运用了奇偶化排序来优化莫队

奇偶化排序不会优化莫队的复杂度却能减少大量常数

奇偶化排序即对于属于奇数块的询问,\(r\)按从小到大排序;对于属于偶数块的排序,\(r\) 从大到小排序。

\(r\) 指针在处理完这个奇数块的问题后,在返回的途中处理偶数块的问题,再向 \(n\) 移动处理下一个奇数块的问题,优化 \(r\) 指针的移动次数。

根据OI-wiki,这样一般可以让程序快 30% 左右

实现

inline void Solve(){
    sort(q+1,q+m+1,cmp);
    int l=1,r=0;
    for(int i=1;i<=m;i++){
        if(q[i].l==q[i].r){
            ans[q[i].id][0]=0;
            ans[q[i].id][1]=1;
            continue;
        }
        while(l>q[i].l) Add(--l);
        while(r<q[i].r) Add(++r);
        while(l<q[i].l) Del(l++);
        while(r>q[i].r) Del(r--);
        //注意上面的顺序
        ans[q[i].id][0]=sum;
        ans[q[i].id][1]=(r-l+1)*(r-l)/2;
    }
}

然后Add和Del看情况写就行

普通莫队这样就没了

先搞几道例题练练手

小B的询问

莫队板子题直接做就行

点击查看代码
#include<bits/stdc++.h>
#define _for(i, a, b) for (int i = a; i <= b; ++i)
#define for_(i, a, b) for (int i = a; i >= b; --i)
#define int long long
/* --------------- fast io --------------- */
using namespace std;
namespace Fread{const int SIZE = (1 << 18);char buf[SIZE],*S,*T;inline char getchar() {if(S==T){T = (S = buf) + fread(buf,1,SIZE,stdin); if(S==T) return '\n';} return *S++;}}
namespace Fwrite {const int SIZE = (1 << 18);char buf[SIZE],*S=buf,*T=buf+SIZE;inline void flush(){fwrite(buf,1,S-buf,stdout), S=buf;}inline void putchar(char c){*S++=c;if(S==T)flush();}struct NTR{ ~NTR() { flush(); }}ztr;}
#ifdef ONLINE_JUDGE
#define getchar Fread::getchar
#define putchar Fwrite::putchar
#endif
namespace Fastio{
    struct Reader{
        template <typename T>
        Reader&operator>>(T&x){char c=getchar();bool f=false;while (c<'0'||c>'9') { if(c == '-')f = true;c=getchar();}x=0;while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}if(f)x=-x;return *this;}
        Reader&operator>>(double & x) {char c=getchar();short f=1,s=0;x=0;double t=0;while((c<'0'||c>'9')&&c!='.'){if(c=='-')f*=-1;c=getchar();}while(c>='0'&&c<='9'&&c!='.')x=x*10+(c^48),c=getchar();if(c=='.')c=getchar();else return x*=f,*this;while(c>='0'&&c<='9')t=t*10+(c^48),s++,c=getchar();while(s--)t/=10.0;x=(x+t)*f;return*this;}
        Reader&operator>>(long double&x){char c=getchar();short f=1,s=0;x=0;long double t=0;while((c<'0'||c>'9')&&c!='.'){if(c=='-')f*=-1;c=getchar();}while(c>='0'&&c<='9'&&c!='.')x=x*10+(c^48),c=getchar();if(c=='.')c=getchar();else return x*=f,*this;while(c>='0'&&c<='9')t=t*10+(c^48),s++,c=getchar();while(s--)t/=10.0;x=(x+t)*f;return*this;}
        Reader&operator>>(__float128&x){char c=getchar();short f=1,s=0;x=0;__float128 t=0;while((c<'0'||c>'9')&&c!='.'){if(c=='-')f*=-1;c=getchar();}while(c>='0'&&c<='9'&&c!='.')x=x*10+(c^48),c=getchar();if(c=='.') c = getchar();else return x*=f, *this;while(c>='0'&&c<='9')t=t*10+(c^48),s++,c=getchar();while(s--)t/=10.0;x=(x+t)*f;return *this;}
        Reader&operator>>(char&c){c=getchar();while(c=='\n'||c==' '||c=='\r')c=getchar();return *this;}
        Reader&operator>>(char*str){int len=0;char c=getchar();while(c=='\n'||c==' '||c=='\r')c=getchar();while(c!='\n'&&c!=' '&&c!='\r')str[len++]=c,c=getchar();str[len]='\0';return *this;}
        Reader&operator>>(string&str){char c=getchar();str.clear();while(c=='\n'||c==' '||c=='\r')c=getchar();while(c!='\n'&&c!=' '&&c!='\r')str.push_back(c),c=getchar();return *this;}
        template<class _Tp>
        Reader&operator>>(vector<_Tp>&vec){for(unsigned i=0;i<vec.size();i++)cin>>vec[i];return *this;}
        template<class _Tp,class _tp>
        Reader&operator>>(pair<_Tp,_tp>&a){cin>>a.first>>a.second;return *this;}
        Reader(){}
    }cin;
    inline int read(){int n;cin>>n;return n;}
    const char endl='\n';
    struct Writer{
    static const int set_precision = 6;
    typedef int mxdouble;
        template<typename T>
        Writer&operator<<(T x){if(x==0)return putchar('0'),*this;if(x<0)putchar('-'),x=-x;static int sta[45];int top=0;while(x)sta[++top]=x%10,x/=10;while(top)putchar(sta[top]+'0'),--top;return*this;}
        Writer&operator<<(double x){if(x<0)putchar('-'),x=-x;mxdouble _=x;x-=(double)_;static int sta[45];int top=0;while(_)sta[++top]=_%10,_/=10;if(!top)putchar('0');while(top)putchar(sta[top]+'0'),--top;putchar('.');for(int i=0;i<set_precision;i++)x*=10;_=x;while(_)sta[++top]=_%10,_/=10;for(int i=0;i<set_precision-top;i++)putchar('0');while(top)putchar(sta[top]+'0'),--top;return*this;}
        Writer&operator<<(long double x){if(x<0)putchar('-'),x=-x;mxdouble _=x;x-=(long double)_;static int sta[45];int top=0;while(_)sta[++top]=_%10,_/=10;if(!top)putchar('0');while(top)putchar(sta[top]+'0'),--top;putchar('.');for(int i=0;i<set_precision;i++)x*=10;_=x;while(_)sta[++top]=_%10,_/=10;for(int i=0;i<set_precision-top;i++)putchar('0');while(top)putchar(sta[top]+'0'),--top;return*this;}
        Writer&operator<<(__float128 x){if(x<0)putchar('-'),x=-x;mxdouble _=x;x-=(__float128)_;static int sta[45];int top=0;while(_)sta[++top]=_%10,_/=10;if(!top)putchar('0');while(top)putchar(sta[top]+'0'),--top;putchar('.');for(int i=0;i<set_precision;i++)x*=10;_=x;while(_)sta[++top]=_%10,_/=10;for(int i=0;i<set_precision-top;i++)putchar('0');while(top)putchar(sta[top]+'0'),--top;return*this;}
        Writer&operator<<(char c){putchar(c);return*this;}
        Writer& operator<<(char*str){int cur=0;while(str[cur])putchar(str[cur++]);return *this;}
        Writer&operator<<(const char*str){int cur=0;while(str[cur])putchar(str[cur++]);return *this;}
        Writer&operator<<(string str){int st=0,ed=str.size();while(st<ed) putchar(str[st++]);return *this;}
        template<class _Tp>
        Writer&operator<<(vector<_Tp>vec){for(unsigned i=0;i<vec.size()-1;i++)cout<<vec[i]<<" ";cout<<vec[vec.size()-1];return *this;}
        template<class _Tp,class _tp>
        Writer&operator<<(pair<_Tp,_tp>a){cout<<a.first<<" "<<a.second;return *this;}Writer(){}
    }cout;
}
#define cin Fastio::cin
#define cout Fastio::cout
#define endl Fastio::endl
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define read Fastio::read
/* --------------- fast io --------------- */
int n,m,k,sqrtn,a[1000001],ans[1000001];
class Mobius{
public:
    int sum,bl[1000001];
    class block{
    public:
        int l,r,id,k;
        inline void Join(int li,int ri,int i){
            l=li,r=ri,
            id=i,k=(li-1)/sqrtn+1;
            return;
        }
		inline bool operator<(block p){
			if(k!=p.k)return l<p.l;
			if(k&1)return r<p.r;
			return r>p.r;
		}
    }blo[100001];
    inline void Join(int l,int r,int i){
        blo[i].Join(l,r,i);
        return;
    }
	inline void Add(int i){
        sum-=bl[i]*bl[i],
        ++bl[i],
        sum+=bl[i]*bl[i];
    }
	inline void Del(int i){
        sum-=bl[i]*bl[i],
        --bl[i],
        sum+=bl[i]*bl[i];
    }
    inline void Solve(){
		sort(blo+1,blo+m+1);
		int l=1,r=0;
		for(int i=1;i<=m;++i){
			while(l>blo[i].l)
                Add(a[--l]);
			while(r<blo[i].r)
                Add(a[++r]);
			while(l<blo[i].l)
                Del(a[l++]);
			while(r>blo[i].r)
                Del(a[r--]);
			ans[blo[i].id]=sum;
		}
	}
}bl;
signed main(){
    freopen("1.in","r",stdin);
    n=read(),m=read(),k=read();
    sqrtn=sqrt(n);
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=1;i<=m;++i){
        int l=read(),r=read();
        bl.Join(l,r,i);
        //不知道为啥这里写bl.Join(read(),read(),i)就WA了
    }
    bl.Solve();
    for(int i=1;i<=m;i++){
        cout<<ans[i]<<endl;
    }

}

标签:int,笔记,学习,bl,while,&&,莫队,getchar
From: https://www.cnblogs.com/LuoTianYi66ccff/p/17927790.html

相关文章

  • Java必知必会系列:机器学习与数据挖掘
    1.背景介绍机器学习和数据挖掘是计算机科学领域的两个重要分支,它们在现实生活中的应用也越来越广泛。机器学习是人工智能的一个分支,它研究如何让计算机自动学习和理解数据,从而实现对未知数据的预测和分类。数据挖掘则是对大量数据进行分析和挖掘,以发现隐藏在数据中的模式和规律,从而......
  • 人工智能算法原理与代码实战:强化学习的基础概念和实践
    1.背景介绍强化学习(ReinforcementLearning,RL)是一种人工智能(AI)的子领域,它旨在解决如何让智能体(如机器人)在环境中取得最佳性能的问题。强化学习的核心思想是通过与环境的互动来学习,而不是通过传统的监督学习方法。在这种学习过程中,智能体通过试错学习,并根据收到的奖励来调整其行为......
  • 人工智能算法原理与代码实战:强化学习与智能交互
    1.背景介绍强化学习(ReinforcementLearning,RL)是一种人工智能(ArtificialIntelligence,AI)技术,它通过在环境中进行交互来学习如何做出最佳决策。强化学习的核心思想是通过在环境中进行试错来学习如何做出最佳决策,而不是通过传统的监督学习方法来学习。强化学习的应用范围广泛,包括......
  • AI人工智能中的数学基础原理与Python实战:深度学习框架与数学基础
    1.背景介绍人工智能(ArtificialIntelligence,AI)和深度学习(DeepLearning,DL)是当今最热门的技术领域之一。它们在图像识别、自然语言处理、语音识别等方面的应用表现卓越,为人类提供了无尽的便利。然而,为了更好地理解和应用这些技术,我们需要掌握其数学基础原理。在本文中,我们将探讨......
  • AI人工智能中的数学基础原理与Python实战:强化学习与决策过程
    1.背景介绍人工智能(ArtificialIntelligence,AI)和机器学习(MachineLearning,ML)是现代科学和技术领域的热门话题。随着数据量的增加,计算能力的提升以及算法的创新,人工智能技术在各个领域的应用也逐渐成为可能。强化学习(ReinforcementLearning,RL)是一种人工智能技术,它旨在让计算......
  • 深度学习原理与实战:深度学习在图像识别中的应用
    1.背景介绍深度学习是人工智能领域的一个热门话题,它是一种通过模拟人类大脑结构和工作方式来解决复杂问题的算法。深度学习的核心思想是通过多层次的神经网络来学习数据的特征,从而实现对复杂问题的解决。图像识别是深度学习的一个重要应用领域,它可以帮助人们自动识别和分类图像,从而......
  • 深度学习原理与实战:批量归一化(Batch Normalization)的理解
    1.背景介绍深度学习是近年来最热门的人工智能领域之一,它是一种通过多层神经网络来处理大量数据并从中学习模式的技术。深度学习的一个主要挑战是训练深层网络的难度,这是因为深层网络容易受到梯度消失或梯度爆炸的影响。在深度学习中,神经网络的输入通常是从数据集中抽取的特征,这些特......
  • 有监督学习的主要技术:从线性回归到支持向量机
    1.背景介绍有监督学习是机器学习的一个重要分支,其主要目标是利用有标签的数据进行模型训练,以便对未知数据进行预测。在这篇文章中,我们将从线性回归到支持向量机,深入探讨有监督学习的主要技术。1.1有监督学习的基本概念有监督学习的基本概念包括训练集、测试集、特征、标签、损失函......
  • 云计算:从基础架构原理到最佳实践之:云计算人工智能与深度学习
    1.背景介绍云计算是一种基于互联网的计算资源共享和分配模式,它允许用户在网络上获取计算资源,而无需购买和维护自己的硬件和软件。云计算的核心思想是将计算任务分解为多个小任务,并将这些小任务分配给不同的计算节点进行处理。这种分布式计算模式有助于提高计算效率、降低成本和提高......
  • 人工智能大模型原理与应用实战:迁移学习实践
    1.背景介绍人工智能(ArtificialIntelligence,AI)是一门研究如何让机器具有智能行为的科学。在过去的几年里,人工智能技术的进步使得许多复杂的任务变得可以自动完成,例如图像识别、语音识别、自然语言处理等。这些技术的核心驱动力是大型神经网络模型,这些模型可以在海量数据上进行训......