ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

分块算法初探 AcWing249 蒲公英

2020-03-17 21:05:34  阅读:334  来源: 互联网

标签:分块 int AcWing249 40 a2 初探 include 蒲公英


https://www.acwing.com/problem/content/description/251/

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

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

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

输入格式

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

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

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

令l=(l0+x-1) mod n+1,r=(r0+x-1) mod n+1,如果l>r,则交换l,r。

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

输出格式

输出 m 行。

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

数据范围

1≤n≤40000,
1≤m≤50000,
1≤ai≤109

输入样例:

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

输出样例:

1 
2 
1

思路:

纯按照书(《算法竞赛进阶指南》)上的方法。

N:蒲公英的数量(序列长度),M:询问次数,T:分块数量。

 

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 typedef long long ll;
  7 using namespace std;
  8 
  9 const int N=5e4+5;
 10 
 11 int a[N],a2[N];//数组a2拷贝数组a。
 12 int b[N];//离散化数据数组。
 13 int pos[N];//元素所在的分块的编号。
 14 int cou[N];//后面算答案时需要用到的count数组。
 15 int l[N],r[N];//分块的左,右端点。
 16 int sum[N][40];分块中某种编号的蒲公英数量的前缀和。
 17 int num[N][40][40];//num[i][j][k]:分块j到分块k中种类i的蒲公英的数量。
 18 int most[40][40],mostn[40][40];//分块中最多的蒲公英种类的数量以及最多的种类的编号。
 19 int n,m,cnt=0;//cnt:出现的蒲公英的种类数。
 20 
 21 void discrete() {
 22     sort(a2+1,a2+n+1);
 23     for(int i=1;i<=n;i++) {
 24         if(i==1||a2[i]!=a2[i-1]) {
 25             b[++cnt]=a2[i];
 26         }
 27     }
 28 }
 29 
 30 int query(int x) {
 31     return lower_bound(b+1,b+cnt+1,x)-b;
 32 }
 33 
 34 int main() {
 35     scanf("%d%d",&n,&m);
 36     for(int i=1;i<=n;i++) {
 37         scanf("%d",&a[i]);
 38         a2[i]=a[i];
 39     }
 40     discrete();//离散化
 41     for(int i=1;i<=n;i++) {
 42         a[i]=query(a[i]);
 43     }
 44     int block=pow((double)n,0.33);//分块
 45     int len=n/block;
 46     for(int i=1;i<=block;i++) {
 47         l[i]=(i-1)*len+1;
 48         r[i]=i*len;
 49     }
 50     if(r[block]<n) {
 51         block++;l[block]=r[block-1]+1;r[block]=n;
 52     }
 53     for(int i=1;i<=block;i++) {//预处理数据
 54         for(int j=1;j<=cnt;j++) {
 55             sum[j][i]=sum[j][i-1];
 56         }
 57         for(int j=l[i];j<=r[i];j++) {
 58             pos[j]=i;
 59             sum[a[j]][i]++;
 60         }
 61     }
 62     for(int i=1;i<=block;i++) {
 63         for(int j=i;j<=block;j++) {
 64             int MAX=0,maxn;
 65             for(int k=1;k<=cnt;k++) {
 66                 num[k][i][j]=sum[k][j]-sum[k][i-1];
 67                 int tmp=num[k][i][j];
 68                 if(MAX<tmp||MAX==tmp&&k<maxn) {
 69                     MAX=tmp;maxn=k;
 70                 }
 71             }
 72             most[i][j]=MAX;mostn[i][j]=maxn;
 73         }
 74     }
 75     int pre=0;
 76     while(m--) {
 77         int x,y;
 78         scanf("%d%d",&x,&y);
 79         x=(x+pre-1)%n+1;
 80         y=(y+pre-1)%n+1;
 81         if(x>y) swap(x,y);
 82         if(pos[x]==pos[y]) {
 83             int MAX=0,maxn;
 84             for(int i=x;i<=y;i++) {
 85                 cou[a[i]]++;
 86                 int tmp=cou[a[i]];
 87                 if(MAX<tmp||MAX==tmp&&a[i]<maxn) {
 88                     MAX=tmp;maxn=a[i];
 89                 }
 90             }
 91             for(int i=x;i<=y;i++) {
 92                 cou[a[i]]--;
 93             }
 94             pre=b[maxn];
 95             printf("%d\n",pre);
 96         }else {
 97             int MAX=0,maxn;
 98             for(int i=x;i<=r[pos[x]];i++) {
 99                 num[a[i]][pos[x]+1][pos[y]-1]++;
100                 int tmp=num[a[i]][pos[x]+1][pos[y]-1];
101                 if(MAX<tmp||MAX==tmp&&a[i]<maxn) {
102                     MAX=tmp;maxn=a[i];
103                 }
104             }
105             for(int i=l[pos[y]];i<=y;i++) {
106                 num[a[i]][pos[x]+1][pos[y]-1]++;
107                 int tmp=num[a[i]][pos[x]+1][pos[y]-1];
108                 if(MAX<tmp||MAX==tmp&&a[i]<maxn) {
109                     MAX=tmp;maxn=a[i];
110                 }
111             }
112             for(int i=x;i<=r[pos[x]];i++) {
113                 num[a[i]][pos[x]+1][pos[y]-1]--;
114             }
115             for(int i=l[pos[y]];i<=y;i++) {
116                 num[a[i]][pos[x]+1][pos[y]-1]--;
117             }
118             int tmp=most[pos[x]+1][pos[y]-1];
119             if(tmp<MAX||tmp==MAX&&maxn<mostn[pos[x]+1][pos[y]-1]) {
120                 pre=b[maxn];
121                 printf("%d\n",pre);
122             }else {
123                 pre=b[mostn[pos[x]+1][pos[y]-1]];
124                 printf("%d\n",pre);
125             }
126         }
127     }
128     return 0;
129 }

 

标签:分块,int,AcWing249,40,a2,初探,include,蒲公英
来源: https://www.cnblogs.com/liaxiaoquan/p/12513332.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有