首页 > 代码库 > CodeForces - 86D 莫队算法

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 莫队算法