经简单分析可知
若是 \(n = 0\),那么以后的比赛将会有周期性:\(1,2,3,\dots,m\)。
进一步来说,一定存在某个值使得,当 k 高于这个值的时候将会呈现于 m 有关的周期性。仔细分析之后可知,这个值为 \(h\times m - n\)。
所以我们只要考虑 k 小于这个临界值的询问(大于的直接取模就行
再将询问离线下来
将 n 次操作视为每次给每个点 +1,记为 \(h[i]\) 。然后排一遍序。设一个指针为 p ,从最低的向高位依次推进,当每遇到一个新的 h 时,我们考虑前p个数都需要再举办到 h 次,然后才能向下枚举。这时我们的问题就只关于这前 p 个数,前 p 个数又一共需要举办 \(h\times p\) 次,所以只要一个询问不大于 \(h\times p\) ,我们就在本次解决,然后需要查询一下前 p 个数的下标第 k 大,这里使用树状数组上倍增解决。
凭借树状数组的小常数,目前成功苟在 rk2
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define lowbit(x) (x & (-x))
char xch,xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
template<typename _T>
inline int read(_T &x)
{
x=0;
int f=1;char ch=getc();
while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int np = 5e5 + 5;
struct query{
int tim;
int id;
friend bool operator<(const query &a,const query &b)
{
return a.tim < b.tim;
}
}qry[np + 10];
int n,h[np + 10],b[np + 10],index[np + 10];
int lg[np + 10];
int tree[np + 10],ans[np + 10];
inline bool cmp(int a,int b)
{
return h[a] < h[b];
}
inline int add(int x)
{
while(x <= n)
{
tree[x] += 1;
x += lowbit(x);
}
}
inline int binary(int kth)
{
int res = 0;
int step = 0;
kth--;
for(int i=lg[n];i>=0;i--)
{
if(step + (1 << i) > n) continue;
if(res + tree[step + (1 << i)] <= kth)
{
res += tree[step + (1 << i)];
step += 1 << i;
}
}
return step + 1;
}
signed main()
{
int m,q;
read(m);
read(n);
read(q);
for(int i=1,x;i<=m;i++)
{
read(x);
h[x] ++ ;
}
int maxn = 0;
for(int i=1;i<=n;i++) maxn = max(maxn , b[i]= h[i]),index[i] = i;
for(int i=2;i<=n;i++) lg[i] = lg[i>>1] + 1;
int lim = maxn * n - m;
sort(b + 1,b + 1 + n);
sort(index + 1,index + 1 + n,cmp);
for(int i=1,x;i<=q;i++)
{
read(x);
x -= m;
qry[i] = (query){x,i};
}
sort(qry + 1,qry + 1 + q);
int p = 1;
int res = 0;
add(index[1]);
for(int i=1;i<=q;)
{
if(qry[i].tim> lim)
{
if((qry[i].tim-lim) % n == 0) ans[qry[i].id] = n;
else ans[qry[i].id] = (qry[i].tim-lim) % n;
i++;
continue;
}
while(b[p + 1] == b[p]) add(index[++p]);
int c = b[p + 1] - b[p];
while(res < qry[i].tim && qry[i].tim <= res + p * c)
{
int g = qry[i].tim - res;
if(g % p == 0) g = binary(p);
else g = binary(g%p);
ans[qry[i].id] = g;
i++;
}
res += p * c;
p++;
add(index[p]);
}
for(int i=1;i<=q;i++)
printf("%lld ",ans[i]);
return 0;
}