信心题--FUOJ2226(莫队算法)

http://acm.fzu.edu.cn/problem.php?pid=2226

信心题,还说是信心题,题目给的真好。但是一点都不像信心题。

又是一个新的算法,莫队算法

莫队算法是一个用数组就可以轻易实现的神奇数据结构,可以处理一类无修改的离线区间查询问题(PS:暂时还没有遇到莫队解决更新区间查询的问题)

  莫队算法可以在O(1),实现[l, r]到[l, r±1] / [l±1, r]的转移,然后我们就可以对所有查询分sqrt(n)块,把每个查询所在的块号当做第一关键字,右端点作为第二关键字升序排列。

  然后进行状态转移即可。

  时间复杂度O(n*sqrt(n)):当i与i+1在同一个块内,则L最多移动sqrt(n),R最多移动n,所以复杂度为O(n*sqrt(n)).

              当i与i+1不在同一块内,则L最多移动2*sqrt(n),R最多移动n,复杂度为O(n*sqrt(n)).

                                                        ------罗茜

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<vector>

using namespace std;
#define N 1001

#define memset(a,b) memset(a,b,sizeof(a))
vector<int>G[N];

struct node
{
    int l,r,id;
}Q[N*10];
int n,q,l[N],r[N],ans[N*10];
int a[N*100];

int cmp(node c,node d)
{
    if(c.l!=d.l)
        return c.l<d.l;
    else
        return c.r<d.r;
}

void solve()
{
    int L=0,R=0;
    for(int i=1;i<=q;i++)
    {
        while(Q[i].l<L)
        {
            L--;
            l[a[L]]--;
        }
        while(Q[i].l>L)
        {
            l[a[L]]++;
            L++;
        }
        while(Q[i].r<R)
        {
            r[a[R]]--;
            R--;
        }
        while(Q[i].r>R)
        {
            R++;
            r[a[R]]++;
        }

        int Max=0;
        for(int j=1;j<=1000;j++)
        {
            if(r[j]<=0)
                continue;
            int u=G[j][r[j]];
            int v=G[j][l[j]+1];
            Max=max(Max,G[j][r[j]]-G[j][l[j]+1]);

        }
        ans[Q[i].id]=Max;
    }
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=1000;i++)
            G[i].clear();
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            G[a[i]].push_back(i);
        }

        memset(l,-1);
        memset(r,-1);

        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d %d",&Q[i].l,&Q[i].r);
            Q[i].id=i;
        }
        sort(Q+1,Q+1+q,cmp);

        solve();

        for(int i=1;i<=q;i++)
        {
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}

/*
5
1 1 1 1 1
3
1 5
3 3
2 5

*/
时间: 2024-08-03 17:59:12

信心题--FUOJ2226(莫队算法)的相关文章

【Luogu】P3709大爷的字符串题(莫队算法)

题目链接 语文题啊…… 看题解发现是让求区间中最多的数的个数,于是果断理解了一会题解……莫队套上完事. sum[i]表示i这个数出现的次数,cnt[i]表示出现i次的数有几个,然后乱搞搞……就好了 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cctype> #include<cmath> #define maxn 3

莫队算法学习小记

算法创始人 莫涛大神. 莫涛队长的算法,%%%%%%%%% 算法简介 算法前提 可以在O(1)的时间内把[l,r]的询问转移到[l-1,r],[l+1,r],[l,r-1],[l,r+1]的询问,而且不需要修改操作,那么就可以使用莫队算法([a,b]表示从a到b的区间,包含a和b) 算法核心 假如有一个询问[l,r]要转移到一个询问[l1,r1],那么需要的时间为O(|l1?l|+|r1?r|),在算法前提下,可以用这么多的时间暴力转移. 但是可以发现有时候有些点会被来回算很多次,这样大量浪费了

【BZOJ3781、2038】莫队算法2水题

[BZOJ3781]小B的询问 题意:有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数 题解:初学莫队算法,差不多明白了用莫队的情况,对于这种离线的,区间长度+1时可O(1)修改答案的题,运用莫队算法是最水的 将n分成sqrt(n)块,将询问按照左端点所在的块为第一关键字,右端点的具体位置为第二关键字排序,然后用指针l,r不断暴力平移到询问的左右端点处,

莫队算法小结以及模板题

被splay折磨了一个星期还是抄模板都wa,调试的时候查数据都发现数据太大不能查的蒟蒻杨澜决定学习莫队算法, 但是 万万没想到 莫队也到处都是坑 ----------------------------------------------题记 莫队这个东西就是一个非常简♂单的类似动规的东西,也是那种不会就一直不会,一看题解秒懂的题,[虽然我看题解也半天看不懂但是只是第一道题,万事开头难嘛(也许吧)] 莫队算法是一种基于分块的离线算法,主要用来解决一些区间的询问[就是暴力],我们需要做的就是把询问

HDU 6278 - Just h-index - [莫队算法+树状数组+二分][2018JSCPC江苏省赛C题]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6278 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Problem Description The h-index of an author is the largest h where he has at least h papers with citations not les

[voj 1551]E - Pairs 2014年武汉大学邀请赛E题 莫队算法

题目大意 有n个数,m个查询,对于每个查询,询问指定区间,有多少个数对的绝对值小于等于2. 解题思路 莫队O^1.5 首先将询问离线处理左端点进行编号,每sqrt(n)个为一组 sort结构体 当左端点编号相同时,比较右端点大小.小的放在前面. 对于每组询问暴力处理,只需处理当前新加入(删除的数字在当前区间内有多少点和它的绝对值只差小于2即可) 唯一要注意的是加点是先更新答案再计数,删点是先计数器-1再更新答案 因为对于每个询问,左端点的修改量不超过sqrt(n) 右端点每一组最坏的复杂度是修改

BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&amp;&amp;学习笔记】

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 9894  Solved: 4561[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两

BZOJ4241 历史研究 莫队算法 堆

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

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,很清楚就是莫队算法,然而做的时候没有学过,回来补题补到 关键是我一直没明白为什么重载小于号