LOJ #6285 分块入门9

题意:区间众数,不带修改,带修改刚看了一眼没看懂cls在讲啥QAQ。

题解:按照代码中那个sqrt(n/2/log2(n))大小分块,可以用均值不等式证明的,就是假设查询和n同级,然后一通爆算就可以得出了。然后预处理出(i,j)块之间最多的数。然后不满一块的部分在vector上二分,这题要先离散化。PS:loj上可以看别人代码学习速度++ 啊。因为把hzwer的1-9看了一遍,时间有限,就随便挑一个了,然后bzoj上的题是权限题,就注册了loj找了份简洁的学着写了,不太习惯,然后有更优秀的做法,看hzwer博客以及cls的论文吧,如果这样预处理直接sqrt(n)是TLE的,应该是卡掉了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+7;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m;
vector<int >vec[maxn];
int gs(int x,int l,int r)
{
    return upper_bound(vec[x].begin(),vec[x].end(),r)-lower_bound(vec[x].begin(),vec[x].end(),l);
}
int a[maxn],b[maxn],bl[maxn];
int f[2000][2000];
int s[maxn];
int get(int l,int r)
{
    if(bl[l]==bl[r])
    {
        int ans=0,ans1=0;
        for(int i=l;i<=r;i++)
        {
            int tmp=gs(a[i],l,r);
            if(tmp>ans1){
                ans=a[i];ans1=tmp;
            }
            if(tmp==ans1)ans=min(a[i],ans);
        }
        return ans;
    }
    int ans0=f[bl[l]+1][bl[r]-1],ans1=gs(ans0,l,r);
    for(int i=l;bl[i]==bl[l];i++)
    {
        int tmp=gs(a[i],l,r);
        if(tmp>ans1)
        {
            ans0=a[i];ans1=tmp;
        }
        if(tmp==ans1)ans0=min(a[i],ans0);
    }
    for(int i=r;bl[i]==bl[r];i--)
    {
        int tmp=gs(a[i],l,r);
        if(tmp>ans1)ans0=a[i],ans1=tmp;
        if(tmp==ans1)ans0=min(a[i],ans0);
    }
    return ans0;
}
int main()
{
    n=read();
    int d=(int)sqrt(n/2/log2(n));
    for(int i=1;i<=n;i++)
    {
        a[i]=read();b[i]=a[i];bl[i]=(i-1)/d+1;
    }
    sort(b+1,b+1+n);
    int ts=unique(b+1,b+1+n)-b-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+ts,a[i])-b;
    for(int i=1;i<=n;i++) vec[a[i]].push_back(i);
    for(int i=1;i<=bl[n];i++)
    {
        memset(s,0,sizeof(s));
        int ans1=0,ans2=0;
        for(int j=(i-1)*d+1;j<=n;j++)
        {
            s[a[j]]++;
            if(s[a[j]]==ans2)
            {
                ans1=min(a[j],ans1);
            }
            else if(s[a[j]]>ans2)
            {
                ans1=a[j];ans2=s[a[j]];
            }
            if(bl[j+1]!=bl[j])
                f[i][bl[j]]=ans1;
        }
    }
    int p=0,q=0;
    for(int i=1;i<=n;i++)
    {
        p=read();q=read();
        if(p>q)swap(p,q);
        cout<<b[get(p,q)]<<"\n";
    }
}

  

 

posted @ 2018-10-26 11:32  Twilight7  阅读(186)  评论(0编辑  收藏  举报