zoukankan      html  css  js  c++  java
  • 巴蜀3540 -- 【Violet 6 最终话】蒲公英

    Description

      原题的时间限制是 2s . 


    亲爱的哥哥:
      你在那个城市里面过得好吗?
      我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……
      最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!
      哥哥你要快点回来哦!
    爱你的妹妹 Violet

      Azure 读完这封信之后微笑了一下。
      “蒲公英吗……”
      
      
      在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。
      为了简化起见,我们把所有的蒲公英看成一个长度为 n 的序列 (a1, a2, a3, ..., an),其中 ai 为一个正整数,表示第 i 棵蒲公英的种类编号。
      而每次询问一个区间[lr],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。
      注意,你的算法必须是在线的。

    Input

      第一行两个整数 nm,表示有 n 株蒲公英,m 次询问。
      接下来一行 n 个空格分隔的整数 ai,表示蒲公英的种类。
      再接下来 m 行每行两个整数 l0, r0,我们令上次询问的结果为 x(如果这是第一次询问,则 x = 0)。
      令 l = (l0 + x - 1) mod n + 1, r = (r0 + x - 1) mod n + 1,如果 l > r,则交换 lr
      最终的询问区间为[lr]。

    Output

      输出 m 行。每行一个整数,表示每次询问的结果。

    Sample Input

    6 3 1 2 3 2 1 2 1 5 3 6 1 5

    Sample Output

    1 2 1

    Hint

      对于 20% 的数据,保证 1 ≤ nm ≤ 3000 。
      对于 100% 的数据,保证 1 ≤ n ≤ 40000,1 ≤ m ≤ 50000,1 ≤ ai ≤ 109 。

    Source

    Violet 6 最终话

    区间求众数,强制在线。

    分块处理,求出每一块区间的众数。对于一次询问的区间,其中众数要么是中间大块的众数,要么是两边小块中的数。

    扫描所求区间中的边缘小块,求其中每个数在区间内的出现次数,找出次数最多的就是区间众数了。

    求数的出现次数,可以预先用vector或者普通数组存这个数在序列中的每一个出现位置,然后二分查找即可。

    不管什么算法,逢二分必挂的被动技能又强行发动了,调二分调了半小时……

    用时比别人多了10000+ms,也是迷。

      1 /*by SilverN*/
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 #include<map>
      9 using namespace std;
     10 const int mxn=50010;
     11 const int block=180;
     12 int read(){
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 int n,m;
     19 //
     20 vector<int>pos[mxn];//数字出现位置 
     21 int v[mxn];//离散化标号对应的数字 
     22 map<int,int>mp;int mct=0;//数字对应的离散化标号 
     23 //
     24 int f[510][510];
     25 int b[mxn];//分块 
     26 //
     27 int a[mxn];
     28 int cnt[mxn];
     29 void init(int x){
     30     memset(cnt,0,sizeof cnt);
     31     int i,j;
     32     int mx=0,num=0;
     33     for(i=(x-1)*block+1;i<=n;i++){
     34         cnt[v[i]]++;
     35         if(cnt[v[i]]>mx || (cnt[v[i]]==mx && a[i]<num)){
     36             mx=cnt[v[i]];
     37             num=a[i];
     38         }
     39         f[x][b[i]]=num;
     40     }
     41     return;
     42 }
     43 int find(int x,int L,int R){
     44 /*    x=mp[x];
     45     int t=upper_bound(pos[x].begin(),pos[x].end(),R)-lower_bound(pos[x].begin(),pos[x].end(),L);
     46     return t;*/
     47     x=mp[x];
     48     int l=0,r=pos[x].size()-1;
     49     int ansl,ansr;
     50     while(l<=r){
     51         int mid=(l+r)>>1;
     52         if(pos[x][mid]<=R)l=mid+1;
     53         else r=mid-1;
     54     }
     55     ansr=l;
     56     l=0,r=pos[x].size()-1;
     57     while(l<=r){
     58         int mid=(l+r)>>1;
     59         if(pos[x][mid]<L)l=mid+1;
     60         else r=mid-1;
     61     }
     62     ansl=l;
     63 //    printf("ask:%d res:%d %d
    ",x,ansl,ansr);
     64     return ansr-ansl;
     65 }
     66 int query(int l,int r){
     67     int mxnum=f[b[l]+1][b[r]-1];
     68     int mx=find(mxnum,l,r);
     69     int i,j;
     70     int ed=min(b[l]*block,r);
     71     for(i=l;i<=ed;i++){
     72         int tmp=find(a[i],l,r);
     73         if(tmp>mx || (tmp==mx && a[i]<mxnum)){
     74             mx=tmp; mxnum=a[i];
     75         }
     76     }
     77     if(b[l]!=b[r])
     78       for(i=(b[r]-1)*block+1;i<=r;i++){
     79           int tmp=find(a[i],l,r);
     80         if(tmp>mx || (tmp==mx && a[i]<mxnum)){
     81             mx=tmp; mxnum=a[i];
     82         }
     83       }
     84     return mxnum;
     85 }
     86 int main(){
     87     n=read();m=read();
     88     int i,j;
     89     for(i=1;i<=n;i++){
     90         a[i]=read();
     91         if(!mp[a[i]])mp[a[i]]=++mct;
     92         v[i]=mp[a[i]];
     93         pos[v[i]].push_back(i);
     94     }
     95     for(i=1;i<=n;++i){b[i]=(i-1)/block+1;}
     96     for(i=1;i<=b[n];i++){init(i);}
     97     int x=0;
     98     int ql,qr;
     99     while(m--){
    100         ql=read();qr=read();
    101         ql=(ql+x-1)%n+1;
    102         qr=(qr+x-1)%n+1;
    103         if(ql>qr)swap(ql,qr);
    104         x=query(ql,qr);
    105         printf("%d
    ",x);
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    【数据结构】线性表&&顺序表详解和代码实例
    【智能算法】超详细的遗传算法(Genetic Algorithm)解析和TSP求解代码详解
    【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)
    【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解
    10. js时间格式转换
    2. 解决svn working copy locked问题
    1. easyui tree 初始化的两种方式
    10. js截取最后一个斜杠后面的字符串
    2. apache整合tomcat部署集群
    1. apache如何启动
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5937144.html
Copyright © 2011-2022 走看看