码迷,mamicode.com
首页 > 编程语言 > 详细

CodeForces - 86D 莫队算法

时间:2017-07-31 22:58:51      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:pre   .net   莫队   时间   运算符重载   turn   problem   date   log   

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

标签:pre   .net   莫队   时间   运算符重载   turn   problem   date   log   

原文地址:http://www.cnblogs.com/Alruddy/p/7265947.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!