[分块][离散化] Bzoj P2724 蒲公英

Description

 

Input

修正一下

l = (l_0 + x – 1) mod n + 1, r = (r_0 + x – 1) mod n + 1

Output

HINT

修正下:

n <= 40000, m <= 50000

 

题解

  • 就是要求区间众数,可以先离散化
  • 我们可以预处理f(i,j)表示第 i 块到第 j 块的众数

  • 那么只要能快速得出一个数在某个区间内出现次数即可,每次只要比较至多2√n+1个元素的出现次数

  • 由于没有修改,只要离散化以后,给每个数 x 开个vector,按顺序存下 x 出现的位置

  • 每次询问 x 时把区间的左右端点放进对应 vector 二分一下即可

代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <map>
 5 #include <vector> 
 6 #include <algorithm>
 7 using namespace std;
 8 const int N=50010;
 9 int n,m,K=200,id,v[N],bl[N],f[510][510];
10 map<int,int>mp;
11 int val[N],cnt[N];
12 vector<int>Q[N];
13 int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
17     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 void pre(int x)
21 {   
22     memset(cnt,0,sizeof(cnt)); int mx=0,ans=0;
23     for (int i=(x-1)*K+1;i<=n;i++)
24     {       
25         cnt[v[i]]++;        
26         int t=bl[i];
27         if (cnt[v[i]]>mx||(cnt[v[i]]==mx&&val[v[i]]<val[ans])) ans=v[i],mx=cnt[v[i]];
28         f[x][t]=ans;
29     }
30 }
31 int query(int l,int r,int x) { return upper_bound(Q[x].begin(),Q[x].end(),r)-lower_bound(Q[x].begin(),Q[x].end(),l); }
32 int query(int a,int b)
33 {
34     int ans,mx;
35     ans=f[bl[a]+1][bl[b]-1],mx=query(a,b,ans);
36     for (int i=a;i<=min(bl[a]*K,b);i++)
37     {
38         int t=query(a,b,v[i]);
39         if (t>mx||(t==mx&&val[v[i]]<val[ans])) ans=v[i],mx=t;
40     }
41     if (bl[a]!=bl[b])
42         for (int i=(bl[b]-1)*K+1;i<=b;i++)
43         {
44             int t=query(a,b,v[i]);
45             if (t>mx||(t==mx&&val[v[i]]<val[ans])) ans=v[i],mx=t;
46         }
47     return ans;
48 }
49 int main()
50 {
51     n=read(),m=read(); int ans=0;
52     for (int i=1;i<=n;i++)
53     {
54         v[i]=read();
55         if (!mp[v[i]]) mp[v[i]]=++id,val[id]=v[i];
56         v[i]=mp[v[i]],Q[v[i]].push_back(i);
57     }
58     for (int i=1;i<=n;i++) bl[i]=(i-1)/K+1;
59     for (int i=1;i<=bl[n];i++) pre(i);
60     for (int a,b;m;m--)
61     {
62         a=read(),b=read();
63         a=(a+ans-1)%n+1,b=(b+ans-1)%n+1;
64         if (a>b) swap(a,b);
65         printf("%d\n",ans=val[query(a,b)]);
66     } 
67 }

 

 

posted @ 2019-07-19 09:31  BEYang_Z  阅读(150)  评论(0编辑  收藏  举报