zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第三场)H Sort the Strings Revision 题解

    题意:

    原串为长度为n(2e6)的 012345678901……

    每次将p[i]位置修改为d[i]形成一个新的串,然后继续在新的串上操作,共n次。

    求总共n+1个串的排名

    这道题上来一看毫无头绪,考场上也就没细想……

    这道题有一个很美妙的性质,就是p[i]是一个排列,这就意味着每个位置只会改变一次,那么我们可以p[i1]=1,p[i2]=2,p[i3]=3……的顺序对这些序列进行处理。

    所以我们采用类似快速排序的方式,找到当前区间p[i]的最小值,看d[i]与p[i]%10的关系,如果d[i]=p[i]%10,说明没变,跳过,否则如果d[i]<p[i]%10,则所有比 i 大的串字典序都比 i 小的串字典序小,反之亦然。

    一开始我找区间最小值的时候用的是线段是,脸黑,T最后5%,改成了笛卡尔树才过……

    值得注意的是,在操作完后排名可能会有重复的,这时候我们需要采用类似后缀数组中的桶排的方式以第一次排序结果为第一关键字,以位置为第二关键字进行排序。

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cmath>
      7 #define N 2000005
      8 using namespace std;
      9 int T,n,ps,pa,pb,pm,p[N];
     10 int ds,da,db,dm,d[N];
     11 struct no{
     12     int left,right,mid;
     13     int mn;
     14 }node[N*4];
     15 void build(int left,int right,int x)
     16 {
     17     node[x].left=left,node[x].right=right;
     18     if(left==right)
     19     {
     20         node[x].mn=left;
     21         return;
     22     }
     23     int mid=(left+right)>>1;
     24     node[x].mid=mid;
     25     build(left,mid,x<<1);
     26     build(mid+1,right,x<<1|1);
     27     if(p[node[x<<1].mn]<p[node[x<<1|1].mn]) node[x].mn=node[x<<1].mn;
     28     else node[x].mn=node[x<<1|1].mn;
     29 }
     30 int Mn;
     31 inline void get(int left,int right,int x)
     32 {
     33     if(node[x].left==left&&node[x].right==right)   
     34     {
     35         if(p[node[x].mn]<p[Mn])
     36         {
     37             Mn=node[x].mn;
     38         }
     39         return;
     40     }
     41     int mid=node[x].mid;
     42     if(left>mid) get(left,right,x<<1|1);
     43     else if(right<=mid) get(left,right,x<<1);
     44     else get(left,mid,x<<1),get(mid+1,right,x<<1|1);
     45 }
     46 int rnk[N],ls[N],rs[N];
     47 void solve(int left,int right,int tmp)
     48 {
     49     if(right<=left)return;
     50     if(p[tmp]==N)return;
     51     if(p[tmp]%10>d[tmp])
     52     {
     53         rnk[left]+=right-tmp;
     54         rnk[tmp+1]-=right-tmp;
     55     }
     56     else
     57     {
     58         rnk[tmp+1]+=tmp-left+1;
     59         rnk[right+1]-=tmp-left+1;
     60     }
     61     solve(left,tmp,ls[tmp]); solve(tmp+1,right,rs[tmp]);
     62 }
     63 int num[N],Sa[N],st[N],top,rt;
     64 int main()
     65 {
     66     scanf("%d",&T);
     67     while(T--)
     68     {
     69         scanf("%d",&n);
     70         scanf("%d%d%d%d",&ps,&pa,&pb,&pm);
     71         for(register int i=0;i<n;++i) p[i]=i;
     72         for(register int i=1;i<=n-1;++i)
     73         {
     74             swap(p[i],p[ps%(i+1)]);
     75             ps=1ll*(1ll*ps*pa+1ll*pb)%pm;
     76         }
     77          
     78         scanf("%d%d%d%d",&ds,&da,&db,&dm);
     79         for(register int i=0;i<n;++i)
     80         {
     81             d[i]=ds%10;
     82             ds=1ll*(1ll*ds*da+db)%dm;
     83         }
     84      
     85         for(register int i=0;i<n;++i)
     86         {
     87             if(p[i]%10==d[i]) p[i]=N;
     88             rnk[i]=0;
     89         }
     90          
     91         rnk[n]=0;
     92         p[n+1]=N+5;
     93         rt=0,top=0;
     94         for(int i=0;i<n;i++)
     95         {
     96             if(p[i]<p[rt]) rt=i;
     97             int k=top;
     98             while(top&&p[st[top]]>p[i]) top--;
     99             if(top) rs[st[top]]=i;
    100             if(top<k) ls[i]=st[top+1];
    101             top++;
    102             st[top]=i;
    103         }
    104         solve(0,n,rt);
    105         for(register int i=0;i<=n;++i) num[i]=0;
    106         for(register int i=1;i<=n;++i)rnk[i]+=rnk[i-1];
    107         for(register int i=0;i<=n;++i) num[rnk[i]]++;
    108         for(register int i=1,m=n+2;i<=m;++i) num[i]+=num[i-1];
    109         for(register int i=n;i>=0;--i)
    110         {
    111             Sa[--num[rnk[i]]]=i;
    112         }
    113         for(register int i=0;i<=n;++i) rnk[Sa[i]]=i;
    114         long long ans=0,xp=1;
    115         for(register int i=0;i<=n;++i)
    116         {
    117             ans=(ans+1ll*rnk[i]*xp%1000000007)%1000000007;
    118             xp=xp*10000019%1000000007;
    119         }
    120         printf("%lld
    ",ans);
    121     }
    122     return 0;
    123 }
    View Code
  • 相关阅读:
    Appium-Java滑动操作
    使用uiautomatorviewer获取元素
    在eclipse中,Python项目遇到:…… from appium import webdriver ImportError: No module named appium
    Python遇到SyntaxError: Non-ASCII character 'xe5' in file D:eclipseworkspace est est_urllib2.py on line2
    在eclipse添加第一次添加Python项目时,提示: Project interpreter not specified
    安装pip环境以及pip常用命令使用
    虚拟机——安装虚拟机时,提示intel VT-x处于禁用状态
    【luogu 3370】【模板】字符串哈希
    【luogu 3378】【模板】堆
    【luogu 3383】【模板】线性筛素数
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13362844.html
Copyright © 2011-2022 走看看