zoukankan      html  css  js  c++  java
  • 【题解】Comet OJ Round 70 简要题解

    【题解】Comet OJ Round 70 简要题解

    A

    将放在地上的书按照从小到大排序后,问题的本质就变成了合并两个序列使得字典序最小。可以直接模拟归并排序。直接用循环和std::merge实现这个过程。复杂度(O(n))

    //@winlere
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int data[100003],in[100003],data2[100003],ans[100003],cnt,n,m;
    int main(){
          scanf("%d%d",&n,&m);
          for(int t=1;t<=m;++t) scanf("%d",data+t),in[data[t]]=1;
          for(int t=1;t<=n;++t) if(!in[t]) data2[++cnt]=t;
          merge(data+1,data+m+1,data2+1,data2+cnt+1,ans+1);
          for(int t=1;t<=n;++t) printf("%d
    ",ans[t]);
          return 0;
    }
    

    B

    由于题目保证了字符串之间互不为前缀,所以由给定字符串的排名连接而成形成排列的字典序就是这个字符串的字典序。

    现在问题就是求出(sum|S|le 1e6)的这么多字符串的字典序,你若肝的话可以直接上SA,但是更简单的办法是建出一颗Trie树随后在上面DFS。匹配最后那个串的时候也可以直接在Tri树上查询。

    现在我们得到了一个排列,问字典序排名第几,直接魔改一下康拓展开即可。复杂度(O(nlog n))

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;  
    const int maxn=1e6+5;
    const int mod=1e9+7;
    char c[maxn];
    struct NODE{
          int son[26],id;
          NODE(){}
          inline int&operator[](int x){return son[x];}
          inline int&operator[](char x){return son[x-'a'];}
    }ac[maxn];
    int data[maxn],cnt,seg[maxn],jc[maxn],inv[maxn],rk[maxn],n,k,ans=1;
    
    inline void insert(const char*c,const int&len,const int&i){
          int now=0;
          for(int t=1;t<=len;++t)
    	    ac[now][c[t]]?now=ac[now][c[t]]:now=ac[now][c[t]]=++cnt;
          ac[now].id=i;
    }
    
    void dfs(const int&now){
          if(ac[now].id) rk[ac[now].id]=++*rk;
          for(int t=0;t<26;++t) if(ac[now][t]) dfs(ac[now][t]);
    }
    
    inline void add(const int&pos,const int&tag){for(int t=pos;t<=n;t+=t&-t) seg[t]+=tag;}
    inline int que(const int&pos,int ret=0){
          for(int t=pos;t>0;t-=t&-t) ret+=seg[t];
          return ret;
    }
    inline int ksm(const int&base,const int&p,int ret=1){
          for(int t=p,b=base;t;t>>=1,b=1ll*b*b%mod) if(t&1) ret=1ll*ret*b%mod;
          return ret;
    }
    inline void pre(const int&n){
          jc[0]=inv[0]=1;
          for(int t=1;t<=n;++t) jc[t]=1ll*jc[t-1]*t%mod;
          inv[n]=ksm(jc[n],mod-2);
          for(int t=n-1;t;--t) inv[t]=1ll*inv[t+1]*(t+1)%mod;
    }
    
    int main(){
          pre(1e6); scanf("%d%d",&n,&k);
          for(int t=1;t<=n;++t) scanf("%s",c+1),insert(c,strlen(c+1),t);
          dfs(0);
          scanf("%s",c+1);
          for(int t=1,cur=1,ed=strlen(c+1);t<=ed;t=cur){
    	    int now=0,f=0;
    	    while(!f)  now=ac[now][c[cur++]],f=ac[now].id;
    	    data[++*data]=rk[f];
          }
          for(int t=1;t<=n;++t) add(t,1);
          for(int t=1,ed=*data,g;t<=ed;++t)
    	    g=que(data[t]),add(data[t],-1),ans=(ans+1ll*(g-1)*jc[n-t]%mod*inv[n-k])%mod;
          printf("%d",ans);
          return 0;
    }
    
    
    

    主办方看起来会让(O(n^2))开O2过是什么鬼...

    C

    在路上

  • 相关阅读:
    .NET中非对称加密RSA算法的密钥保存
    WGS84经纬度坐标到北京54高斯投影坐标的转换[转]
    [APPS] HTC Footprints & HTC Locations for MikG 2.x Read more:
    firefox+ssh无法看youtube视频的解决方案
    【转】sdemon命令实践
    How to share a custom ArcMap command (DLL)
    【转】sdemon命令实践
    红旗桌面版本最新运用法子和结果解答100例8
    红旗Linux桌面4.1文本安装过程图解(二)
    Ubuntu把在效能器范畴起更重要的脚色
  • 原文地址:https://www.cnblogs.com/winlere/p/11606331.html
Copyright © 2011-2022 走看看