信心题--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

*/

 

posted @ 2016-05-18 12:35  啦咯  阅读(592)  评论(0编辑  收藏  举报