zoukankan      html  css  js  c++  java
  • 蒲公英

    --------一道 做了好久好久好久好久好久好久好久的题

       (洛谷4168)

     

    题意: 给定一个序列 多次询问

       每次询问一个区间 求这个区间里的众数

       算法必须是在线的

     

    思路:众数不具有区间可加性  于是只能分块了 (事实上分块真的很慢,最后也是卡过去的)  

       -关于分多少块的问题 实践证明分len=30 是很合适的(我也不知道为什么 是dalao告诉我的 qwq)

       对于每个询问[l,r] 设l处于第x块 r处于第y块

       那么此区间的众数只可能是 第x+1到第y-1块中间的整块部分的 或是x,y块中包含于询问区间的不足整块部分的

       然后采取分块一般套路 :“大段维护,局部朴素” 

       此题大段中的答案可以初始化得出 

       但是“局部朴素”也还是要优化的(不要太朴素了啦) 

              定义一个vector d[] : d[i]中存第i个数出现过的位置

    假设 d[1]={1,4,7,8,9} 那么[3,7]区间内第一个数的出现次数就为 3-2+1=2  这里还要用到二分

       

      还有要注意的是 序列长度为n 但是序列元素可不是1-n之间的数 可能会非常的大 这里还要用到离散化

     

        (代码有一点bug 开O2会RE)

      code

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<vector>
      7 #define yes(i,a,b) for(register int i=a;i<=b;i++)
      8 #define M 50100
      9 #define N 3000
     10 using namespace std;
     11 int read()
     12 {
     13   int x=0,y=1;char c;c=getchar();
     14   while(c<'0'||c>'9') {if(c=='-') y=-1;c=getchar();}
     15   while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-'0';c=getchar();} return x*y;
     16 }
     17 int n,m,len,kn,l_ans;
     18 int b[M],c[M],id[M],tot[M],f[N][N];
     19 vector<int> d[M];
     20 struct node {int val,pos;} a[M];
     21 bool cmp(node x,node y) {return x.val<y.val;}
     22 void init1()
     23 {
     24   sort(a+1,a+n+1,cmp);int num=0;
     25   yes(i,1,n)
     26     {
     27       if(a[i].val!=a[i-1].val) c[a[i].pos]=++num,b[num]=a[i].val;
     28       else c[a[i].pos]=num;
     29     }
     30   yes(i,1,n) d[c[i]].push_back(i);
     31 }
     32 void init2(int x)
     33 {
     34   int maxn=0,aans=0;
     35   memset(tot,0,sizeof(tot));
     36   yes(i,x,n)
     37     {
     38       tot[c[i]]++;
     39       if(tot[c[i]]>maxn||(tot[c[i]]==maxn&&c[i]<aans))
     40         {maxn=tot[c[i]];aans=c[i];}
     41       f[id[x]][id[i]]=aans;
     42     }
     43 }
     44 int efl(int x,int y)
     45 {
     46   int l=0,r=d[x].size()-1,aans=0;
     47   while(l<=r)
     48     {
     49       int mid=(l+r)/2;
     50       if(d[x][mid]>=y) aans=mid,r=mid-1;
     51       else l=mid+1;
     52     }
     53   return aans;
     54 }
     55 int efr(int x,int y)
     56 {
     57   int l=0,r=d[x].size()-1,aans=0;
     58   while(l<=r)
     59     {
     60       int mid=(l+r)/2;
     61       if(d[x][mid]<=y) aans=mid,l=mid+1;
     62       else r=mid-1;
     63     }
     64   return aans;
     65 }
     66 int query(int x,int y)
     67 {
     68   if(x>y) swap(x,y);
     69   int p=id[x],q=id[y],aans=0,maxn=0;
     70   if(q<=p+1)
     71     {
     72       yes(i,x,y)
     73       {
     74         int l,r;
     75         l=efl(c[i],x);
     76         r=efr(c[i],y);
     77        if((r-l+1>maxn)||(r-l+1==maxn&&c[i]<aans))
     78           {aans=c[i];maxn=r-l+1;}
     79       }
     80     }
     81   else
     82     {
     83       aans=f[p+1][q-1];maxn=efr(aans,y)-efl(aans,x)+1;
     84       yes(i,x,p*len)
     85       {
     86         int l,r;
     87         l=efl(c[i],x);
     88         r=efr(c[i],y);
     89         if((r-l+1>maxn)||(r-l+1==maxn&&c[i]<aans))
     90           {aans=c[i];maxn=r-l+1;}
     91       }
     92       yes(i,(q-1)*len+1,y)
     93       {
     94         int l,r;
     95         l=efl(c[i],x);
     96         r=efr(c[i],y);
     97        if((r-l+1>maxn)||(r-l+1==maxn&&c[i]<aans))
     98          {aans=c[i];maxn=r-l+1;}
     99       }
    100     }
    101   return aans;
    102 }
    103 int main()
    104 {
    105   //freopen("1.in","r",stdin);
    106   //freopen("1.out","w",stdout);
    107   n=read();m=read();len=30;kn=n/len;
    108   yes(i,1,n) a[i].val=read(),a[i].pos=i;
    109   yes(i,1,n) yes(j,(i-1)*len+1,i*len) id[j]=i;
    110   if(kn*len<n) yes(i,kn*len+1,n) id[i]=kn+1;kn++;
    111   init1();
    113   yes(i,1,kn) init2((i-1)*len+1);
    116   yes(i,1,m)
    117     {
    118       int l=read(),r=read();
    119       l=(l+l_ans-1)%n+1;r=(r+l_ans-1)%n+1;
    120       l_ans=b[query(l,r)];
    121       printf("%d
    ",l_ans);
    122     }
    123   return 0;
    124 }
    光伴随的阴影
  • 相关阅读:
    [NOI2004]cashier 郁闷的出纳员
    [HNOI2004]宠物收养所
    [HNOI2002]营业额统计
    浅谈算法——莫比乌斯反演
    浅谈算法——splay
    [POI2006]Tet-Tetris 3D
    BZOJ2733 [HNOI2012]永无乡 【线段树合并】
    UOJ279 【UTR #2】题目交流通道
    UOJ278 【UTR #2】题目排列顺序
    POJ2761 Feed the dogs
  • 原文地址:https://www.cnblogs.com/forward777/p/10124784.html
Copyright © 2011-2022 走看看