2724: [Violet 6]蒲公英
Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1536 Solved: 529
[ Submit][ Status][ Discuss]
Description
Input
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
Output
Sample Input
1 2 3 2 1 2
1 5
3 6
1 5
Sample Output
2
1
HINT
修正下:
n <= 40000, m <= 50000
解题思路:先分块,离散,然后可以处理出i块到j块的答案f[i][j]
询问时只需要暴力记录两边的多出来的数是否比f[lg+1][rg-1]
更优即可。sum[i][j]表示i这个数在前j块有sum[i][j]个。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
int n,m,a[51000],ogg;
int l,r,x,cnt,og,h;
struct ss
{
int zhi,dui;
}q[51000],f[510][510];
int sum[51000][510];
int sz[51000],w[51000];
int g[51000];
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0'||y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
bool cmp(ss x,ss y)
{
return x.zhi<y.zhi;
}
void init()
{
for (int i=1;i<=n;++i)a[i]=read(),q[i].zhi=a[i],q[i].dui=i;
sort(q+1,q+n+1,cmp); cnt=0;
for (int i=1;i<=n;++i)
{
if (q[i].zhi!=q[i-1].zhi)++cnt; g[cnt]=a[q[i].dui];
a[q[i].dui]=cnt;
}
}
void work()
{
og=int(sqrt(n)); h=n/og;
if (n%og!=0) ++h;
for (int i=1;i<=h;++i)
{
memset(sz,0,sizeof(sz));
for (int j=(i-1)*og+1;j<=min(i*og,n);++j) ++sz[a[j]];
for (int j=1;j<=cnt;++j)
{
sum[j][i]=sum[j][i-1]+sz[j];
}
}
for (int i=1;i<=h;++i)
for (int j=i;j<=h;++j)
{
f[i][j]=f[i][j-1];
for (int k=(j-1)*og+1;k<=min(j*og,n);++k)
{
if (sum[a[k]][j]-sum[a[k]][i-1]>f[i][j].zhi || (sum[a[k]][j]-sum[a[k]][i-1]==f[i][j].zhi && a[k]<f[i][j].dui) )
{
f[i][j].zhi=sum[a[k]][j]-sum[a[k]][i-1];
f[i][j].dui=a[k];
}
}
}
}
int main()
{
freopen("main.in","r",stdin);
freopen("me.out","w",stdout);
n=read(); m=read();
init(); work();
l=0; r=0; x=0;
for (int i=1;i<=m;++i)
{
l=read(); r=read();
l=(l+x-1)%n+1; r=(r+x-1)%n+1;
if (l>r) swap(l,r);
int lg,rg; lg=l/og; rg=r/og;
if (l%og!=0) ++lg; if (r%og!=0) ++rg; ++lg; --rg; ogg=0;
if (lg>rg)
{
rg=0; lg=0;
for (int j=l;j<=r;++j) w[++ogg]=a[j];
}else
{
for (int j=l;j<=(lg-1)*og;++j) w[++ogg]=a[j];
for (int j=(rg*og+1);j<=r;++j) w[++ogg]=a[j];
}
sort(w+1,w+ogg+1);
int wei=0; int ans=f[lg][rg].zhi; x=f[lg][rg].dui; w[ogg+1]=0;
for (int j=2;j<=ogg+1;++j)
{
if (w[j]!=w[j-1])
{
if (j-1-wei+sum[w[j-1]][rg]-sum[w[j-1]][lg-1]>ans || (j-1-wei+sum[w[j-1]][rg]-sum[w[j-1]][lg-1]==ans && w[j-1]<x))
{
x=w[j-1]; ans=j-1-wei+sum[w[j-1]][rg]-sum[w[j-1]][lg-1];
}
wei=j-1;
}
}
printf("%d\n",g[x]); x=g[x];
}
}