https://ac.nowcoder.com/acm/contest/5668/H
p[i]%10==d[i],那么经过这次操作是不变的
那么把s0-sn为中会变的拿出来,按顺序建笛卡尔树,下标为k+1,val为p[k],因为越前面对字典序影响越大,而且p是0-n-1的排列,所以笛卡尔树不会有问题
然后dfs笛卡尔树,每个节点将一段区间分为了两部分,根据变化后数字变大还是变小了,去考虑先dfs右子区间还是先dfs左子区间,ans[i]的编号也就是优先dfs到的顺序的编号
#include<bits/stdc++.h>
using namespace std;
const int maxl=2e6+10;
const int mod=1e9+7;
int n,tot,cnt,rt;
int p[maxl],d[maxl],ans[maxl],mi;
struct node
{
int k,val,fa,ls,rs,l,r;
}tr[maxl];
inline int build()
{
int k;
for(int i=1;i<=tot;i++)
{
k=i-1;
while(tr[k].val>tr[i].val)
k=tr[k].fa;
tr[i].fa=k;
tr[tr[k].rs].fa=i;
tr[i].ls=tr[k].rs;
tr[k].rs=i;
}
return tr[0].rs;
}
inline void prework()
{
scanf("%d",&n);
int seed,a,b,mod;
scanf("%d%d%d%d",&seed,&a,&b,&mod);
for(int i=0;i<=n-1;i++)
p[i]=i;
for(int i=1;i<=n-1;i++)
{
swap(p[seed%(i+1)],p[i]);
seed=(1ll*seed*a+b)%mod;
}
scanf("%d%d%d%d",&seed,&a,&b,&mod);
for(int i=0;i<=n-1;i++)
{
d[i]=seed%10;
seed=(1ll*seed*a+b)%mod;
}
tot=0;
tr[0]=node{0,-1,0,0,0,0,n};
for(int i=0;i<=n-1;i++)
if(d[i]!=p[i]%10)
tr[++tot]=node{i+1,p[i],0,0,0,0,0};
rt=build();
tr[rt].l=0;tr[rt].r=n;
}
inline void dfs(int u)
{
int ls=tr[u].ls,rs=tr[u].rs;
if(ls && rs)
{
tr[ls].l=tr[u].l;tr[ls].r=tr[u].k-1;
tr[rs].l=tr[u].k;tr[rs].r=tr[u].r;
if(tr[u].val%10<d[tr[u].k-1])
{
dfs(ls);
dfs(rs);
}
else
{
dfs(rs);
dfs(ls);
}
}
else if(ls)
{
tr[ls].l=tr[u].l;tr[ls].r=tr[u].k-1;
if(tr[u].val%10<d[tr[u].k-1])
{
dfs(ls);
for(int i=tr[u].k;i<=tr[u].r;i++)
ans[i]=cnt++;
}
else
{
for(int i=tr[u].k;i<=tr[u].r;i++)
ans[i]=cnt++;
dfs(ls);
}
}
else if(rs)
{
tr[rs].l=tr[u].k;tr[rs].r=tr[u].r;
if(tr[u].val%10<d[tr[u].k-1])
{
for(int i=tr[u].l;i<tr[u].k;i++)
ans[i]=cnt++;
dfs(rs);
}
else
{
dfs(rs);
for(int i=tr[u].l;i<tr[u].k;i++)
ans[i]=cnt++;
}
}
else
{
if(tr[u].val%10<d[tr[u].k-1])
{
for(int i=tr[u].l;i<=tr[u].r;i++)
ans[i]=cnt++;
}
else
{
for(int i=tr[u].k;i<=tr[u].r;i++)
ans[i]=cnt++;
for(int i=tr[u].l;i<tr[u].k;i++)
ans[i]=cnt++;
}
}
}
inline void mainwork()
{
cnt=0;
dfs(rt);
}
inline void print()
{
long long sum=0,t=1;
for(int i=0;i<=n;i++)
{
sum=(sum+ans[i]*t%mod)%mod;
t=t*10000019%mod;
}
printf("%lld\n",sum);
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}