牛客多校2020 第三场-H Sort the Strings Revision(笛卡尔树+分治
题意:https://ac.nowcoder.com/acm/contest/5668/H
给你一些修改操作让你给所有改完后的结果排个序
思路:
很容易想到分治
建立笛卡尔树后左右跑跑,先跑变小的,一开始dfs没想好写了半天,其实按照分配 rank 的思路去写就行了,先分配左边的,有小的再分配小的
1 ll n; 2 int son[N][2]; 3 ll p[N],d[N],ans[N]; 4 int stak[N]; 5 6 void dfs(int l,int r,int x,int rk) 7 { 8 if(l>r)return; 9 if(l==r) 10 { 11 ans[l]=rk; 12 return; 13 } 14 if(p[x]==inf||d[x]>p[x]%10) 15 { 16 dfs(l,x-1,son[x][0],rk); 17 dfs(x,r,son[x][1],rk+x-l); 18 } 19 else 20 { 21 dfs(x,r,son[x][1],rk); 22 dfs(l,x-1,son[x][0],rk+r-x+1); 23 } 24 return; 25 } 26 27 signed main() 28 { 29 int T; 30 sc("%lld",&T); 31 while(T--) 32 { 33 sc("%lld",&n); 34 ll p_seed,p_a,p_b,p_mod,d_seed,d_a,d_b,d_mod; 35 scanf("%lld%lld%lld%lld",&p_seed,&p_a,&p_b,&p_mod); 36 scanf("%lld%lld%lld%lld",&d_seed,&d_a,&d_b,&d_mod); 37 for(int i=0;i<n;i++) p[i]=i; 38 for(int i=1;i<n;i++){ 39 swap(p[p_seed%(i+1)],p[i]); 40 p_seed=(1ll*p_seed*p_a+1ll*p_b)%p_mod; 41 } 42 for(int i=0;i<n;i++){ 43 d[i]=d_seed%10; 44 d_seed=(1ll*d_seed*d_a+1ll*d_b)%d_mod; 45 } 46 47 for(int i=n+1;i>1;--i) 48 { 49 p[i]=p[i-2],d[i]=d[i-2]; 50 if(p[i]%10==d[i])p[i]=inf; 51 } 52 n++; 53 p[1]=d[1]=inf; 54 55 int top=0; 56 for(int i=1;i<=n;++i) 57 { 58 while(top&&p[i]<p[stak[top]]) 59 son[i][0]=stak[top--]; 60 if(top) 61 son[stak[top]][1]=i; 62 stak[++top]=i; 63 } 64 dfs(1,n,stak[1],0); 65 // for(int i=1;i<=n;++i) 66 // pr("%lld%c",ans[i]," \n"[i==n]); 67 int res=0,temp=1; 68 for(int i=1;i<=n;++i) 69 res=(res+ans[i]*temp%mod)%mod,temp=temp*10000019%mod; 70 pr("%lld\n",res); 71 // pr("%lld\n",stak[1]); 72 } 73 return 0; 74 }