题解:P14764 [Opoi 2025] CCD 的不难题
dandelayer · · 题解
提供一个比 std 好写些的分块做法,码量只有 std 的约 1/3。
Part 1:预处理
我们将整个序列每
由于有
Part 2:查询
对于每一次查询,我们先找出
接下来我们思考可能会有哪些数出现次数可能为
因此,我们可以再扫一遍区间
因为对
由于区间
Part 3:最小化时间复杂度
由上述分析可知该分块算法的总复杂度为 unsigned short 而不是 int。
附代码:
#include<bits/stdc++.h>
using namespace std;
int n,B,a[50001],q,l,r,k,ans;
unsigned short cnt[41][41][50001],hd[41][41][50001],nxt[41][41][50001];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;B=pow(n,2.0/3);
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int l=1;l<=(n-1)/B+1;l++)
{
for(int r=l;r<=(n-1)/B+1;r++)
{
int l2=(l-1)*B+1,r2=min(n,r*B);
for(int i=l2;i<=r2;i++)
{
cnt[l][r][a[i]]++;
}
for(int i=1;i<=n;i++)
{
nxt[l][r][i]=hd[l][r][cnt[l][r][i]];
hd[l][r][cnt[l][r][i]]=i;
}
}
}
cin>>q;
for(int i=1;i<=q;i++)
{
cin>>l>>r>>k;
l^=ans;r^=ans;k^=ans;ans=0;
int L=(l-1)/B+1,R=(r-1)/B+1;
int l2=(L-1)*B+1,r2=min(n,R*B);
for(int j=l2;j<l;j++)
{
cnt[L][R][a[j]]--;
}
for(int j=r+1;j<=r2;j++)
{
cnt[L][R][a[j]]--;
}
for(int j=l2;j<l;j++)
{
if(cnt[L][R][a[j]]==k)ans=max(ans,a[j]);
}
for(int j=r+1;j<=r2;j++)
{
if(cnt[L][R][a[j]]==k)ans=max(ans,a[j]);
}
for(int j=hd[L][R][k];j;j=nxt[L][R][j])
{
if(cnt[L][R][j]==k)
{
ans=max(ans,j);
break;
}
}
for(int j=l2;j<l;j++)
{
cnt[L][R][a[j]]++;
}
for(int j=r+1;j<=r2;j++)
{
cnt[L][R][a[j]]++;
}
cout<<ans<<'\n';
}
}