【分析】其实是个水题,用一个可变数组(vector或者链表)来记录每个a[i]对应的所有下标,很容易可以通过预处理让每个链表内下标都有序,然后每次传递接力棒的时候只要让a[i]链表最小的值移动到a[i-1]链表,但是移动的时候不是会使得a[i-1]不是有序了?没关系,只要在剩余传递次数小于当前链表内元素个数的时候才会产生影响,那么这个时候只要把这个链表内元素排一次序即可,由于每个元素最大只有10^6,所以可以通过计数排序做到O(N)复杂度,那么总的复杂度还是O(N)的。这里链表我用了链式前向星来存既剩内存还提高效率。
【AC CODE】889ms
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 10000000+10,MAXM = 10000000*2+10;
int head[MAXN],sz[MAXN],tol,nxt[MAXM],to[MAXM];
int a[MAXN];
long long seed;
int rand(int l, int r) {
static long long mo=1e9+7, g=78125;
return l+((seed*=g)%=mo)%(r-l+1);
}
inline void add_edge(int u, int v)
{
nxt[tol] = head[u],to[tol] = v;
if(-1 == head[u]) sz[u] = 1;
else sz[u]++;
head[u] = tol++;
}
int cnt[MAXN],num[MAXN];
void my_sort(int id)
{
int mx = 0,s = 0;
clc(cnt,0);
for(int i = head[id]; ~i; i = nxt[i])
{
num[s++] = i;
cnt[to[i]]++;
mx = max(mx,to[i]);
}
s = 0;
repe(i,0,mx)
{
while(cnt[i]) to[num[s++]] = i,cnt[i]--;
}
}
int main()
{
#ifdef SHY
freopen("d:\\1.txt", "r", stdin);
#endif
int t;
scanf("%d", &t);
while(t--)
{
int n,q,mx = 0;
scanf("%d%d%lld",&n,&q,&seed);
int sum=rand(q, 10000000);
for(int i=1; i<=n; i++) {
a[i]=rand(0, sum/(n-i+1));
sum-=a[i];
}
a[rand(1, n)]+=sum;
/*n = 4,q = 3;
a[1] = 2,a[2] = 2,a[3] = 3,a[4] = 2;*/
repe(i,1,n) mx = max(mx,a[i]);
tol = 0;
clc(head,-1);
per(i,n,1) add_edge(a[i],i);
int p = mx,sot = false;
rep(i,0,q)
{
while(!sz[p]) p--;
if(!sot && q-i < sz[p])
{
my_sort(p);
sot = true;
//continue;
}
int &h = head[p];
int id = to[h];
sz[p]--;
h = nxt[h];
add_edge(p-1,id);
}
int ans = 0;
repe(i,0,mx)
{
for(int j = head[i]; ~j; j = nxt[j])
ans ^= (i+to[j]);
}
printf("%d\n", ans);
}
return 0;
}