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;

}
时间: 2024-11-11 04:34:14

CodeForces - 86D 莫队算法的相关文章

codeforces 617 E. XOR and Favorite Number(莫队算法)

题目链接:http://codeforces.com/problemset/problem/617/E 题目: 给你a1 a2 a3 ··· an 个数,m次询问:在[L, R] 里面又多少中 [l, r] 使得 al xor al+1 xor ··· ar 为 k. 题解: 本题只有区间查询没有区间修改,而且数据量不大(10w),所以可以用离线的方法解决. 使用莫队算法来解决,就需要O(1)的修改[L, R+1] .[L, R-1].[L+1, R].[L-1, R]. 详细的莫队可以百度学一

Codeforces Round #340 (Div. 2) E. XOR and Favorite Number 【莫队算法 + 异或和前缀和的巧妙】

任意门:http://codeforces.com/problemset/problem/617/E E. XOR and Favorite Number time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output Bob has a favorite number k and ai of length n. Now he asks yo

[莫队算法 线段树 斐波那契 暴力] Codeforces 633H Fibonacci-ish II

题目大意:给出一个长度为n的数列a. 对于一个询问lj和rj.将a[lj]到a[rj]从小到大排序后并去重.设得到的新数列为b,长度为k,求F1*b1+F2*b2+F3*b3+...+Fk*bk.当中F为斐波那契数列.F1=F2=1.对每一个询问输出答案模m. 区间查询离线 用莫队算法 开棵权值线段树,然后用斐波那契的性质update F(n+m)=F(n+1)*F(m)+F(n)*F(m-1); #include<cstdio> #include<cstdlib> #includ

莫队算法小结(Markdown版)

wtf,最近挖坑有点小多啊,没办法>_<容我先把糖果公园A了再来写这个吧= =看看今天能不能A掉 好吧,我承认我第二天才把糖果公园A掉>_<下面把这篇小结补上 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m个询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为0则输出01 仔细观察发现,令x表示x这个值出现的次

莫队算法小结

唔,想有更加舒爽的阅读体验请移步http://mlz000.logdown.com/posts/252433-mo-algorithm-summary 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为则输出0/1 仔细观察发现,令x表示x个值出现的次数,则每次询问[l,r]区

D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input standard input output standard output An array of positive integers a1,?a2,?...,?an is given. Let us consider its arbitrary subarray al,?al?+?1...,?ar, where 1?

莫队算法

Beautiful Girl 题意 给定一个长度为 n 的序列 a[1], a[2], ..., a[n] . m 组询问 (l, r, K) , 求区间 [l, r] 去除重复的数之后的第 K 小. n, m <= 100000 . 分析 莫队算法 + 值域分块. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #include &

BZOJ4241 历史研究 莫队算法 堆

欢迎访问~原文出处--博客园-zhouzhendong&AK 去博客园看该题解 题目 Description IOI国历史研究的第一人--JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 1.

(普通的)莫队算法简单介绍

莫队算法(由莫涛发明的)是一种离线的暴力算法(至少我这么认为).使用莫队算法的条件是,知道一个区间[l, r]的结果,那么也可以快速知道[l + 1, r],[l - 1, r], [l, r - 1], [l, r + 1]这四个区间的结果.于是可以想到,直接通过这样转移来解决一些问题.当然有些出题人机智,故意卡这种暴力,让你从头跑到尾然后从尾跑到头,于是时间复杂度高达O(n2) 而莫队算法就是通过改变处理询问的顺序来降低时间复杂度. 比如说现在知道一个区间[l1, r1],又要转移到[l2,