莫队算法模板

一道简单的莫队算法题:
https://vjudge.net/contest/171364#problem/I
莫队的一般写法:

// CodeForces 86D
#include
#define pb push_back 
#define mp make_pair
using namespace std;

const int maxn=2e5+7;
typedef long long ll;

struct Mo{
    int l,r,t,id;
}p[maxn];

ll a[maxn];

ll f[1000007];

ll ans[maxn];

int n,Q;

ll now=0;

bool operator<(const Mo &a,const Mo &b)
{
    if(a.t==b.t) return a.rreturn a.tvoid dec(int x)
{
    ll v=a[x];
    now+=(-2*f[v]+1)*v;
    f[v]--;
}

void add(int x)
{
    ll v=a[x];
    now+=(2*f[v]+1)*v;
    f[v]++;
}

int main()
{
    int i,j,k,T;
    scanf("%d%d",&n,&Q);
    for(i=1;i<=n;++i)
    {
        scanf("%lld",&a[i]);
    }
    int q=700;
    for(i=1;i<=Q;++i)
    {
        scanf("%d%d",&p[i].l,&p[i].r);
        p[i].t=p[i].l/q;
        p[i].id=i;
    }

    sort(p+1,p+Q+1);

    int l=1,r=0;
    for(i=1;i<=Q;++i)
    {
        while(lwhile(l>p[i].l) add(--l);
        while(rwhile(r>p[i].r) dec(r--);
        ans[p[i].id]=now;
    }

    for(i=1;i<=Q;++i)
    {
        printf("%I64d\n",ans[i]);
    } 

    return 0;
}

稍难一点的莫队(莫队+分块)
http://acm.uestc.edu.cn/#/problem/show/1753
别人的题解:
http://hzwer.com/5749.html
我的代码:

// UESTC - 1753
#include
#define pb push_back 
#define mp make_pair
using namespace std;

const int maxn=1e5+7,maxm=1e6+7;
typedef long long ll;

//快速读入 
inline void read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;
    n=q*w;
}
//快速输出
inline void write(int x){  
    static const int maxlen=100;  
    static char s[maxlen];  
        if (x<0) {   putchar('-'); x=-x;}  
    if(!x){ putchar('0'); return; }  
    int len=0; for(;x;x/=10) s[len++]=x % 10+'0';  
    for(int i=len-1;i>=0;--i) putchar(s[i]);  
} 

struct Mo{
    int l,r,id,a,b;
}p[maxm];

int ans[maxm];

int n,m;

struct Part{
    int l,r,num;
}part[maxn];

int f[maxn],s[maxn];

int ntop[maxn];

int q;

bool operator<(const Mo &a,const Mo &b)
{
    if(a.l/q==b.l/q) return a.rreturn a.l/qvoid add(int x)
{
    int v=s[x];
    f[v]++;
    if(f[v]==1) part[ntop[v]].num++;
}

void dec(int x)
{
    int v=s[x];
    f[v]--;
    if(f[v]==0) part[ntop[v]].num--;
}

int get_ans(int l,int r)
{
    int L=ntop[l],R=ntop[r];
    int res=0,i;
    if(L==R)
    {
        for(i=l;i<=r;++i)
        {
            if(f[i])
              res++;
        }
        return res;
    }
    for(i=L+1;i<=R-1;++i)
      res+=part[i].num;
    for(i=l;i<=part[L].r;++i)
      if(f[i]) res++;
    for(i=part[R].l;i<=r;++i)
      if(f[i]) res++;
    return res;
}

void doit_mo()
{
    int l=1,r=0;
    for(int i=1;i<=m;++i)
    {
        while(lwhile(l>p[i].l) add(--l);
        while(rwhile(r>p[i].r) dec(r--);
        ans[p[i].id]=get_ans(p[i].a,p[i].b);
    }
}

int main()
{
    int i,j,k,T;
    read(n);read(m);

    q=sqrt(n);

    for(i=1;i<=n;++i)
    {
        ntop[i]=(i-1)/q+1;
    }

    for(i=1;i<=n;i+=q)
    {
        part[ntop[i]].l=i;
        part[ntop[i]].r=i+q-1;
    }

    for(i=1;i<=n;++i) 
    {
        read(s[i]);
    }
    for(i=1;i<=m;++i)
    {
        read(p[i].l);
        read(p[i].r);
        read(p[i].a);
        read(p[i].b);
        p[i].id=i;
    }

    sort(p+1,p+1+m);

    doit_mo();


    for(i=1;i<=m;++i)
      write(ans[i]),putchar('\n');
    /*
    for(i=1;i<=m;++i)
      printf("%d\n",ans[i]);
    */
    return 0;
}

————————
关于分块的方法:
莫队算法模板_第1张图片
用刘大爷的话说,第一种满足基本复杂度,第二种在m很大时更优
————————
当带上修改时:
http://blog.csdn.net/hzj1054689699/article/details/51866615

你可能感兴趣的:(模板)