题解报告——蒲公英

题目传送门

题目背景

亲爱的哥哥:

你在那个城市里面过得好吗?

我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……

最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!

哥哥你要快点回来哦!

爱你的妹妹 Violet

Azure 读完这封信之后微笑了一下。

“蒲公英吗……”

题目描述

在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。

为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 (a1,a2..an)(a_1,a_2..a_n)(a1,a2..an),其中 aia_iai 为一个正整数,表示第i棵蒲公英的种类编号。

而每次询问一个区间 [l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。

注意,你的算法必须是在线的

输入输出格式

输入格式:

第一行两个整数 n,m ,表示有n株蒲公英,m 次询问。

接下来一行n个空格分隔的整数 aia_iai ,表示蒲公英的种类

再接下来m 行每行两个整数 l0,r0l_0,r_0l0,r0,我们令上次询问的结果为 x(如果这是第一次询问, 则 x=0)。

l=(l0+x−1)modn+1,r=(r0+x−1)modn+1l=(l_0+x-1)\bmod n + 1,r=(r_0+x-1) \bmod n + 1l=(l0+x1)modn+1,r=(r0+x1)modn+1,如果 l>r,则交换 l,r 。

最终的询问区间为[l,r]。

输出格式:

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

输入输出样例

输入样例#1: 复制
6 3 
1 2 3 2 1 2 
1 5 
3 6 
1 5
输出样例#1: 复制
1 
2 
1

说明

对于 20% 的数据,保证 1≤n,m≤30001\le n,m \le 30001n,m3000。

对于 100% 的数据,保证 1≤n≤40000,1≤m≤50000,1≤ai≤1091\le n \le 40000,1\le m \le 50000,1\le a_i \le 10^91n40000,1m50000,1ai109。


【思路分析】

分块好题,分块大法好,暴力操标算。。。囧rz!!!

这道题看得出就是一道区间求众数的题目。

大致思路是这样的,首先我们要充分发挥分块暴力大法好的精神

先暴力预处理出每个块内每种蒲公英的个数,

然后求出对每个块而言的前缀和,

于是这样我们就可以区间查询任意两个块之间每种蒲公英的数量了

然后我们预处理出任意两个块之间的众数

最后对于每组询问,我们先找到夹在它们中间的块,

如果两个块相差超过了1,那么我们先取出中间块的众数,作为我们的answer,然后对旁边两个块暴力处理众数(此处注意判断时要加上中间的蒲公英)。

如果这个两个块r-l<=1,那么我们暴力求众数。。。

最后记得离散化一下即可。。。


【代码实现】

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cctype>
  5 #include<cmath>
  6 using namespace std;
  7 inline void read(int &x)
  8 {
  9     int f;char ch;
 10     while(!isdigit(ch=getchar())&&ch!='-'); ch=='-'?(f=-1,x=0):(f=1,x=ch-'0');
 11     while(isdigit(ch=getchar())) x=x*10+ch-'0';x=x*f;
 12 }
 13 const int N=4e4+5,M=205;
 14 struct sd{
 15     int id,w;
 16 }num[N];
 17 int rank[N],back[N],n,nn,m,tot,sqr;
 18 int sum[M][N],mx[M][M],time[N],lastans;
 19 bool cmp(sd a,sd b) {return a.w<b.w;}
 20 int GG(int l,int r)
 21 {
 22     int now=0;
 23     for(int i=l;i<=r;i++)
 24     {
 25         time[rank[i]]++;
 26         if(time[now]<time[rank[i]]) now=rank[i];
 27         if(time[now]==time[rank[i]]&&rank[i]<now) now=rank[i];
 28     }
 29     return now;
 30 }
 31 int ask(int l,int r)
 32 {
 33     int ll=(l-1)/sqr+1,rr=(r-1)/sqr+1,lr,rl,mx1,mx2;
 34     if(rr-ll<=1)
 35     {
 36         int res=GG(l,r);
 37         for(int i=l;i<=r;i++) time[rank[i]]--;
 38         return res;
 39     }
 40     int now=mx[ll+1][rr-1];
 41     lr=ll*sqr,rl=(rr-1)*sqr+1;
 42     GG(l,lr),GG(rl,r);
 43     for(int i=l;i<=lr;i++)
 44     {
 45         if(sum[rr-1][now]-sum[ll][now]+time[now]<sum[rr-1][rank[i]]-sum[ll][rank[i]]+time[rank[i]]) now=rank[i];
 46         if(sum[rr-1][now]-sum[ll][now]+time[now]==sum[rr-1][rank[i]]-sum[ll][rank[i]]+time[rank[i]]&&rank[i]<now) now=rank[i];
 47     }
 48     for(int i=rl;i<=r;i++)
 49     {
 50         if(sum[rr-1][now]-sum[ll][now]+time[now]<sum[rr-1][rank[i]]-sum[ll][rank[i]]+time[rank[i]]) now=rank[i];
 51         if(sum[rr-1][now]-sum[ll][now]+time[now]==sum[rr-1][rank[i]]-sum[ll][rank[i]]+time[rank[i]]&&rank[i]<now) now=rank[i];
 52     }
 53     for(int i=l;i<=lr;i++) time[rank[i]]--;
 54     for(int i=rl;i<=r;i++) time[rank[i]]--;
 55     return now;
 56 }
 57 int main()
 58 {
 59     read(n),read(m);
 60     sqr=sqrt(n),nn=(n-1)/sqr+1;
 61     for(int i=1;i<=n;i++) read(num[i].w),num[i].id=i;
 62     sort(num+1,num+1+n,cmp);
 63     for(int i=1;i<=n;i++)
 64     {
 65         if(num[i].w!=num[i-1].w) tot++;
 66         rank[num[i].id]=tot,back[tot]=num[i].w;
 67     }
 68     for(int i=1;i<=n;i++)
 69     for(int j=(i-1)/sqr+1;j<=nn;j++) 
 70     sum[j][rank[i]]++;
 71     for(int i=1;i<=nn;i++)
 72     {
 73         int l,r;
 74         for(int j=i;j<=nn;j++)
 75         {
 76             mx[i][j]=mx[i][j-1];
 77             l=(j-1)*sqr+1,r=j*sqr;
 78             for(int id=l;id<=r;id++)
 79             {
 80                 time[rank[id]]++;
 81                 if(sum[j-1][rank[id]]-sum[i-1][rank[id]]+time[rank[id]]>sum[j-1][mx[i][j]]-sum[i-1][mx[i][j]]+time[mx[i][j]])
 82                 mx[i][j]=rank[id];
 83                 if(sum[j-1][rank[id]]-sum[i-1][rank[id]]+time[rank[id]]==sum[j-1][mx[i][j]]-sum[i-1][mx[i][j]]+time[mx[i][j]]&&rank[id]<mx[i][j])
 84                 mx[i][j]=rank[id];
 85             }
 86             for(int id=l;id<=r;id++) time[rank[id]]--;
 87         }
 88     }
 89     /*for(int i=1;i<=nn;i++)
 90     for(int j=i;j<=nn;j++) printf("[%d %d %d]\n",i,j,mx[i][j]);*/
 91     while(m--)
 92     {
 93         int l,r;
 94         read(l),read(r);
 95         l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1;
 96         if(l>r) swap(l,r);
 97         lastans=back[ask(l,r)];
 98         printf("%d\n",lastans);
 99     }
100     return 0;
101 }

猜你喜欢

转载自www.cnblogs.com/genius777/p/9693743.html