[Violet] 蒲公英
题目背景
亲爱的哥哥:
你在那个城市里面过得好吗?
我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……
最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!
哥哥你要快点回来哦!
爱你的妹妹 Violet
Azure 读完这封信之后微笑了一下。
“蒲公英吗……”
题目描述
在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。
为了简化起见,我们把所有的蒲公英看成一个长度为 \(n\) 的序列 \(\{a_1,a_2..a_n\}\),其中 \(a_i\) 为一个正整数,表示第 \(i\) 棵蒲公英的种类编号。
而每次询问一个区间 \([l, r]\),你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。
注意,你的算法必须是在线的。
输入格式
第一行有两个整数,分别表示蒲公英的数量 \(n\) 和询问次数 \(m\)。
第二行有 \(n\) 个整数,第 \(i\) 个整数表示第 \(i\) 棵蒲公英的种类 \(a_i\)。
接下来 \(m\) 行,每行两个整数 \(l_0, r_0\),表示一次询问。输入是加密的,解密方法如下:
令上次询问的结果为 \(x\)(如果这是第一次询问,则 \(x = 0\)),设 \(l=((l_0+x-1)\bmod n) + 1,r=((r_0+x-1) \bmod n) + 1\)。如果 \(l > r\),则交换 \(l, r\)。
最终的询问区间为计算后的 \([l, r]\)。
输出格式
对于每次询问,输出一行一个整数表示答案。
样例 #1
样例输入 #1
6 3
1 2 3 2 1 2
1 5
3 6
1 5
样例输出 #1
1
2
1
提示
数据规模与约定
- 对于 \(20\%\) 的数据,保证 \(n,m \le 3000\)。
- 对于 \(100\%\) 的数据,保证 \(1\le n \le 40000\),\(1\le m \le 50000\),\(1\le a_i \le 10^9\),\(1 \leq l_0, r_0 \leq n\)。
我们可以先浅浅的打一下暴力
点击查看代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int N =40000,M=40000+5;
int n,m,a[M];
int zh[M][3005];
map <int,int> mp,fmp;
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m;
int cnt=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(!mp[a[i]])mp[a[i]]=++cnt,fmp[cnt]=a[i];
for(int j=1;j<=cnt;j++)
{
zh[i][j]=zh[i-1][j];
}
zh[i][mp[a[i]]]++;
}
// cout<<cnt;
int l,r,ans=0;
for(int i=1;i<=m;i++)
{
cin>>l>>r;
l=(l+ans-1)%n+1;
r=(r+ans-1)%n+1;
if(l>r)swap(l,r);
int tms=0;
for(int j=1;j<=cnt;j++)
{
if(zh[r][j]-zh[l-1][j]>tms)
{
ans=fmp[j];
tms=zh[r][j]-zh[l-1][j];
}else if(zh[r][j]-zh[l-1][j]==tms)
{
ans=min(fmp[j],ans);
}
}
cout<<ans<<endl;
}
return 0;
}
会超时,以为他在求前缀和时候占用的时间太长,首先无论如何要离散化一下(有本事你不),这时候我们会想到分块,每个块中存种类最多的那个答案,但是会有多个块连在一起的区间,所以开一个数组mp记录从\(i\)到\(j\)块中的答案,我们可以暴力预处理一下,然后考虑到有散块,这部分暴力就行,但还要预处理一下整块中存在的a[i]数量,开一个数组sum记录从\(i\)开始\(a[i]\)的出现次数,与散块相加,统计,选出最优的即可
点击查看代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int N =40000,M=40000+5,G=505;
int n,m,a[M],tong[M],st[G],en[G],mp[G][M],sum[G][M],sq,belong[M];
int read()
{
int f=1,x=0;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-f;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
void init()
{
sq=sqrt(n);
for(int i=1;i<=sq;i++)
{
st[i]=n/sq*(i-1)+1;
en[i]=n/sq*i;
}
en[sq]=n;
for(int i=1;i<=sq;i++)
{
for(int j=st[i];j<=en[i];j++)
{
belong[j]=i;
}
// size[i]=en[i]-st[i]+1;
}
for(int i=1;i<=n;i++)
{
for(int j=belong[i];j<=sq;j++)
{
sum[j][a[i]]++;
}
}
for(int i=1;i<=sq;i++)
{
memset(tong,0,sizeof(tong));
for(int j=i;j<=sq;j++)
{
mp[i][j]=mp[i][j-1];
int res=mp[i][j];
for(int k=st[j];k<=en[j];k++)
{
tong[a[k]]++;
if(tong[a[k]]>tong[res]||(tong[res]==tong[a[k]]&&a[k]<res))
{
res=a[k];
}
}
mp[i][j]=res;
// cout<<"&&"<<st[i]<<" "<<en[j]<<" "<<res<<endl;
}
}
memset(tong,0,sizeof(tong));
}
int query(int l,int r)
{
int res=0;
if(belong[l]==belong[r])
{
for(int i=l;i<=r;i++)
{
tong[a[i]]++;
if(tong[a[i]]>tong[res]||(tong[res]==tong[a[i]]&&a[i]<res))
{
res=a[i];
}
}
for(int i=l;i<=r;i++)tong[a[i]]=0;
}else
{
int tmpres=mp[belong[l]+1][belong[r]-1];
int tmpans=sum[belong[r]-1][tmpres]-sum[belong[l]][tmpres];
// cout<<tmpans<<"^^^^";
for(int i=l;i<=en[belong[l]];i++)
{
if(!tong[a[i]])
{
tong[a[i]]+=sum[belong[r]-1][a[i]]-sum[belong[l]][a[i]];
}
if(a[i]==tmpres)tmpans++;
}
for(int i=st[belong[r]];i<=r;i++)
{
if(!tong[a[i]])
{
tong[a[i]]+=sum[belong[r]-1][a[i]]-sum[belong[l]][a[i]];
}
if(a[i]==tmpres)tmpans++;
}
for(int i=l;i<=en[belong[l]];i++)
{
tong[a[i]]++;
if(tong[a[i]]>tong[res]||(tong[res]==tong[a[i]]&&a[i]<res))
{
res=a[i];
}
}
for(int i=st[belong[r]];i<=r;i++)
{
tong[a[i]]++;
if(tong[a[i]]>tong[res]||(tong[res]==tong[a[i]]&&a[i]<res))
{
res=a[i];
}
}
if(tmpans>tong[res]||(tmpans==tong[res]&&tmpres<res))
{
res=tmpres;
// cout<<"%%"<<endl;
}
for(int i=l;i<=en[belong[l]];i++)tong[a[i]]=0;
for(int i=st[belong[r]];i<=r;i++)tong[a[i]]=0;
}
return res;
}
int b[M];
void write(int x)
{
if(x>=10)write(x/10);
putchar(x%10+'0');
}
signed main()
{
// ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// freopen("P4168_1.in","r",stdin);
n=read();m=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
b[i]=a[i];
}
sort(b+1,b+1+n);
int tot=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
}
init();
// cout<<cnt;
int l,r,ans=0;
for(int i=1;i<=m;i++)
{
l=read();r=read();
l=(l+ans-1)%n+1;
r=(r+ans-1)%n+1;
// cout<<l<<" "<<r<<endl;
if(l>r)swap(l,r);
ans=query(l,r);
ans=b[ans];
write(ans);
// ans=b[ans];
putchar('\n');
}
return 0;
}