码迷,mamicode.com
首页 > 其他好文 > 详细

Frequent values

时间:2018-03-08 14:07:36      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:.com   info   暴力   lag   namespace   main   can   ++   返回   

技术分享图片

↑这是题面,赵老师%%%


我们很容易就能想到缩点。将连续的一段数字缩为一个点。然后在点上跑st表。

类似于分块的想法

如果有零碎的块,就暴力计算。中间的块使用st表O(1)计算

总时间复杂度(nlogn)
O(n)分块。

O(nlogn)预处理。

O(1)查询。

#include<iostream>
#include<cstdio>
using namespace std;
int in[100000],n;
struct node
{
    int x;
    int y;
    int len;
};//块的结构体
node k[1000000];//块
int ll;//块的个数
int st[1000010][20];//在块上的st表
int log[1000010];//以2为底的log
int pow[20];//二的n次方
int flag[1000010];//原数组中第i项属于第几个块
void st_()//st表初始化
{
    log[0]=0;
    log[1]=0;
    for(int i=2;i<=ll;i++)
        log[i]=log[i>>1]+1;//递推log
    pow[0]=1;
    for(int i=1;i<=log[ll];i++)
        pow[i]=pow[i-1]<<1;//处理2^N次方
    for(int i=1;i<=ll;i++)
        st[i][0]=k[i].len;
    for(int i=1;i<=log[ll];i++)//正常的st表
        for(int j=1;j+pow[i]-1<=ll;j++)
            st[j][i]=max(st[j][i-1],st[j+pow[i-1]][i-1]);
}
void first_work()//分块
{
    int now=-0x7fffffff;
    for(int i=1;i<=n;i++)
    {
        if(now!=in[i])//分块。遇到一个不同于当前的数据。则表示要进行下一步的分块
        {
            k[ll].y=i-1;//前一个块的右节点
            k[ll].len=k[ll].y-k[ll].x+1;//前一个块的长度
            k[++ll].x=i;//现在块的左节点
            now=in[i];//更新
        }
        flag[i]=ll;//处理第i项在那一块里
    }
    k[ll].y=n;
    k[ll].len=k[ll].y-k[ll].x+1;
}
int st_check(int begin,int end)//连续的块查询。
{
    if(begin>end)//这种情况发生在两个零块相邻。所以中间没有整块
        return -0x7fffffff;//返回无穷小
    int l=end-begin+1;
    return max(st[begin][log[l]],st[end-pow[log[l]]+1][log[l]]);//O(1)查询
}
int bl_check(int begin,int end)//零块查询
{
    return end-begin+1;//直接计算,因为一个块中没有不同的数字
}
int main()
{
    scanf("%d",&n);
    int m;
    scanf("%d",&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&in[i]);
    first_work();
    st_();
    int a,b;
    int ans;
    for(int i=1;i<=m;i++)
    {
        ans=-0x7ffffff;
        scanf("%d%d",&a,&b);
        ans=max(ans,bl_check(a,k[flag[a]].y));//分成两个零块和一堆连续的整块
        ans=max(ans,st_check(flag[a]+1,flag[b]-1));
        ans=max(ans,bl_check(k[flag[b]].x,b));
        printf("%d\n",ans);
    }
}

Frequent values

标签:.com   info   暴力   lag   namespace   main   can   ++   返回   

原文地址:https://www.cnblogs.com/Lance1ot/p/8527499.html

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