CodeForces - 86D 莫队算法

Posted 可达龙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 86D 莫队算法相关的知识,希望对你有一定的参考价值。

http://codeforces.com/problemset/problem/86/D

莫队算法就是调整查询的顺序,然后暴力求解。

每回可以通过现有区间解ans(l,r)得到区间(l+1,r),(l-1,r),(l,r+1),(l,r-1)的区间解。

调整方式http://blog.csdn.net/bossup/article/details/39236275

这题比那个还要简单,查询的是K^2*Z,很清楚就是莫队算法,然而做的时候没有学过,回来补题补到

关键是我一直没明白为什么重载小于号运算符会比重写比较函数要费时间,运算符重载挂在第44个例子,交了10多遍。

Orz,Orz 又交了几遍,一样的代码有时会跑不出来,然后又在比较函数上优化,勉强能看了。

不过还是弱到不知道那个2s钟怎么跑的。。。

 

代码最终版本

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
const int MAXN = 1e6 + 20;
LL cnt[MAXN];
int pos[N];
LL ans = 0;
int sqr;
struct query
{
    int l,r,id;
};
query q[N];
int a[N];
LL res[N];
bool cmp(query a, query b)
{
    if(pos[a.id] == pos[b.id])
        return a.r < b.r;
    return pos[a.id] < pos[b.id];
}
void update(int x, int d)
{
    ans += cnt[a[x]]*2*d*a[x] + a[x];
    cnt[a[x]] += d;
}

void init()
{
    memset(cnt, 0, sizeof(cnt));
    memset(a, 0, sizeof(a));
    memset(q, 0, sizeof(q));
}
int n, m, l ,r;
int main( )
{
   //     freopen("D.in", "r", stdin);
    init();
    scanf("%d%d", &n, &m);
    sqr = sqrt(m);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= m; i++)
    {
        scanf("%d%d", &q[i].l, &q[i].r);
        pos[i] = q[i].l/sqr;
        q[i].id = i;
    }
    sort(q+1, q+m+1, cmp);
    ans = 0;
    int pl = 1, pr = 0;
    for(int i = 1; i <= m; i++)
    {
        int id = q[i].id;

        while(pl < q[i].l)
        {
            update(pl, -1);
            pl++;
        }

        while(pl > q[i].l)
        {
            pl--;
            update(pl, 1);
        }

        while(pr < q[i].r)
        {
            pr++;
            update(pr, 1);
        }

        while(pr > q[i].r)
        {
            update(pr, -1);
            pr--;
        }
        res[id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%I64d\\n", res[i]);

    return 0;

}

 

之前版本:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
const int MAXN = 1e6 + 20;
LL cnt[MAXN];
LL ans = 0;
int sqr;
struct query
{
    int l,r,id;
};
query q[N];
int a[N];
LL res[N];
bool cmp(query a, query b)
{
    if((a.l-1)/sqr == (b.l-1)/sqr)
        return a.r < b.r;
    return (a.l-1)/sqr < (b.l-1)/sqr;
}
void update(int x, int d)
{
    ans -= cnt[a[x]]*cnt[a[x]]*a[x];
    cnt[a[x]] += d;
    ans += cnt[a[x]]*cnt[a[x]]*a[x];
}

void init()
{
    memset(cnt, 0, sizeof(cnt));
    memset(a, 0, sizeof(a));
    memset(q, 0, sizeof(q));
}
int n, m, l ,r;
int main( )
{
   //     freopen("D.in", "r", stdin);
    init();
    scanf("%d%d", &n, &m);
    sqr = sqrt(m);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= m; i++)
    {
        scanf("%d%d", &q[i].l, &q[i].r);
        q[i].id = i;
    }
    sort(q+1, q+m+1, cmp);
    ans = 0;
    int pl = 1, pr = 0;
    for(int i = 1; i <= m; i++)
    {
        int id = q[i].id;

        while(pl < q[i].l)
        {
            update(pl, -1);
            pl++;
        }

        while(pl > q[i].l)
        {
            pl--;
            update(pl, 1);
        }

        while(pr < q[i].r)
        {
            pr++;
            update(pr, 1);
        }

        while(pr > q[i].r)
        {
            update(pr, -1);
            pr--;
        }
        res[id] = ans;
    }
    for(int i = 1; i <= m; i++)
        printf("%I64d\\n", res[i]);

    return 0;

}

 

以上是关于CodeForces - 86D 莫队算法的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces 86D Powerful array(莫队算法)

Powerful array CodeForces - 86D (莫队算法)

Codeforces 86D Powerful array(莫队)

CodeForces - 86D Powerful array (莫队)

Powerful array CodeForces - 86D(莫队)

「CF86D」Powerful array 解题报告