zoukankan      html  css  js  c++  java
  • LOJ 2303 「NOI2017」蚯蚓排队——链表+哈希表

    题目:https://loj.ac/problem/2303

    想到合并的时候可以只考虑接口附近的50个,但不太会分析复杂度,而且没有清楚地想到用哈希值对应个数。

    看了题解才会……

    一直想用 splay ,其实链表就可以。用 unsigned long long 就不会被卡。

    不能用 map ,而是要用哈希表把字符串的哈希值映射到个数上。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll unsigned long long
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int mod=998244353; const ll bs=10009;
    const int N=2e5+5,m2=1e6+3,M=1e7+5,K=55;
    
    int n,m,vl[N],pr[N],nt[N],ct[M];
    ll tp[M],p[K],bin[K];char s[M];//ll!!! not int
    namespace H{
      int hd[m2+5],xnt,nxt[M];ll to[M];
      int get(ll x)
      {
        int h=x%m2;
        for(int i=hd[h];i;i=nxt[i])
          if(to[i]==x)return i;
        to[++xnt]=x;nxt[xnt]=hd[h];hd[h]=xnt;
        return xnt;
      }
    }
    void mrg(int x,int y,bool fx)
    {
      if(!fx){nt[x]=y; pr[y]=x;} else{y=nt[x]; nt[x]=pr[y]=0;}
      int tot=0,cr=y;
      while(cr)
        {
          tot++; tp[tot]=(tp[tot-1]*bs+vl[cr]);
          cr=nt[cr]; if(tot==49)break;
        }
      int tt=0; cr=x;
      while(cr)
        {
          tt++; p[tt]=(p[tt-1]+vl[cr]*bin[tt-1]);
          cr=pr[cr]; if(tt==49)break;
        }
      for(int i=tt;i;i--)
        for(int j=1;j<=tot;j++)
          {
        if(i+j>50)break;
        ll h=p[i]*bin[j]+tp[j];
        int tp=H::get(h);
        if(fx)ct[tp]--;
        else ct[tp]++;
          }
    }
    int main()
    {
      n=rdn();m=rdn();
      bin[0]=1;
      for(int i=1;i<=50;i++)
        {
          bin[i]=bin[i-1]*bs;
        }
      for(int i=1;i<=n;i++)
        {
          vl[i]=rdn();
          int k=H::get(vl[i]); ct[k]++;
        }
      for(int i=1,op,x,y;i<=m;i++)
        {
          op=rdn();
          if(op==1){ x=rdn();y=rdn();mrg(x,y,0);}
          if(op==2){ x=rdn();mrg(x,0,1);}
          if(op==3)
        {
          scanf("%s",s+1); x=rdn(); y=strlen(s+1);
          for(int j=1;j<=y;j++)
            tp[j]=(tp[j-1]*bs+(s[j]-'0'));
          int ans=1;
          for(int j=x;j<=y;j++)
            {
              ll h=tp[j]-tp[j-x]*bin[x];
              int tp=H::get(h);
              ans=(long long)ans*ct[H::get(h)]%mod;
            }
          printf("%d
    ",ans);
        }
        }
      return 0;
    }
  • 相关阅读:
    Android入门第六篇之ListView (一)
    mysql触发器的作用及语法
    查询记录时rs.previous()的使用
    Microsoft Visual C++ Runtime Library Runtime Error的解决的方法
    Ubuntu中编译链接Opencv应用的简便方式
    24点经典算法
    CMS系统简介(从简介到使用)
    编程学习资源
    Django是什么
    Thinkphp中的自动验证
  • 原文地址:https://www.cnblogs.com/Narh/p/10975756.html
Copyright © 2011-2022 走看看