• loj 6285 数列分块入门 9


    题解:分块。哇,毒瘤题ORZ,提交了好几页TLE,不过是好题。先离散化再处理。区间的众数有三种情况:①L块中L及之后的部分  ②R块中R及之前的部分。  ③L,R之间若干个整块范围的众数。预处理每两个整块之间的众数,边块暴力,块的大小玄学开。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100010;
    int w[maxn],scatter[maxn],n,block,cnt,dp[maxn/50][maxn/50],nn,t[maxn];
    vector<int> v[maxn];
    map<int,int>imapi;
    int get(int x);
    void pre(int x);
    int check(int l,int r);
    int find(int l,int r,int w);
    int main()
    {
      int i,l,r;
      scanf("%d",&n);
      block=50;
      cnt=n/block;
      if(n%block) cnt++;
      for(i=1;i<=n;i++)
       {
        scanf("%d",&w[i]);
        if(!imapi[w[i]])
         {
            imapi[w[i]]=++nn;
            scatter[nn]=w[i];
         }
        w[i]=imapi[w[i]];
        v[w[i]].push_back(i);
       }
      for(i=1;i<=cnt;i++) pre(i);
      for(i=0;i<n;i++)
      {
        scanf("%d%d",&l,&r);
        int index=check(l,r);
        printf("%d
    ",scatter[index]);
      }
      system("pause");
      return 0;
    }
    int get(int x)
    {return (x-1)/block+1;}
    int find(int l,int r,int w)
    {return upper_bound(v[w].begin(),v[w].end(),r)-lower_bound(v[w].begin(),v[w].end(),l);}
    void pre(int x)
    {
      memset(t,0,sizeof(t));
      int index,i,mmax=0,ans=0;
      for(i=(x-1)*block+1;i<=n;i++)
      {
        index=get(i);
        t[w[i]]++;
        if(t[w[i]]>mmax||(t[w[i]]==mmax&&scatter[w[i]]<scatter[ans]))
          mmax=t[w[i]],ans=w[i];
        dp[x][index]=ans;
      }
    }
    int check(int l,int r)
    {
      int i,pre,end,ans=0,mmax=0,x;
      pre=get(l);end=get(r);
      if(pre==end)
       {
        for(i=l;i<=r;i++)
         {
           x=find(l,r,w[i]);
           if(x>mmax||(x==mmax&&scatter[w[i]]<scatter[ans]))
            mmax=x,ans=w[i];
         }
       }
       else
       {
        ans=dp[get(l)+1][get(r)-1];
        mmax=find(l,r,ans);
        for(i=l;i<=min(n,pre*block);i++)
         {
           x=find(l,r,w[i]);
           if(x>mmax||(x==mmax&&scatter[w[i]]<scatter[ans]))
             mmax=x,ans=w[i];
         }
        for(i=(end-1)*block+1;i<=r;i++)
         {
           x=find(l,r,w[i]);
           if(x>mmax||(x==mmax&&scatter[w[i]]<scatter[ans]))
             mmax=x,ans=w[i];
         }
       }
       return ans;
    }
    本博客仅为本人学习,总结,归纳,交流所用,若文章中存在错误或有不当之处,十分抱歉,劳烦指出,不胜感激!!!
  • 相关阅读:
    测试JavaScript
    从零开始部署小型企业级虚拟桌面 -- Vmware Horizon View 6 For Linux VDI -- 概念简介
    怎样向IT行业的朋友说明《圣经》的重要性
    关于爱剪辑、会声会影、美图秀秀
    快速登录IRC网络聊天室
    如何写一篇好的搭建教程
    从零开始部署小型企业级虚拟桌面 -- Vmware Horizon View 6 For Linux VDI
    Oracle工程师技能树
    论万金油的悲哀
    自定义地图开发(一)
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/11306554.html
Copyright © 2020-2023  润新知