• P4715 「英语」Z 语言


    题解:

    平衡树维护hash值

    为了支持加入删除操作 x*base^y 其中y为他是第k大

    同一般的维护方法,我们不用对每个节点维护他的hash值

    而是只用记录他的x值(他的位置) 然后通过updata的时候维护

    很神奇的一点是

    我用了mo数就炸了。。。

    直接自然溢出就好了。。。应该是哪里正负没处理好。。

    另外还wa了一个点。。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll N=5e5+10;
    const ll Base=20020415;
    ll n,m,q,cl[N],a[N],b[N];
    map<ll,ll> M;
    struct Splay{
      ll count2[N],data[N],ls[N],rs[N],fa[N],v[N],vv[N],root=0,cnt=0;
      void updata(ll x)
      {
        count2[x]=count2[ls[x]]+count2[rs[x]]+1;
        data[x]=(data[ls[x]]+1ll*data[rs[x]]*cl[count2[ls[x]]+1]
        +cl[count2[ls[x]]]*v[x]);
      }
      void rotate(ll x,ll y)
      {
        ll fa1=fa[x];
        if (y==1)
        {
          rs[fa1]=ls[x];
          if (ls[x]) fa[ls[x]]=fa1;
        } else
        {
          ls[fa1]=rs[x];
          if (rs[x]) fa[rs[x]]=fa1;
        }
        fa[x]=fa[fa1];
        if (fa[fa1])
        {
          ls[fa[fa1]]==fa1?ls[fa[fa1]]=x:rs[fa[fa1]]=x; 
        }
        fa[fa1]=x;
        if (y==1) ls[x]=fa1; else rs[x]=fa1;
        updata(fa1); updata(x);
      }
      void splay(ll x,ll goal)
      {
        ll fa1=fa[x];
        while (fa1!=goal)
        {
          if (fa[fa1]==goal)
            x==ls[fa1]?rotate(x,2):rotate(x,1);
          else 
          if (fa1==ls[fa[fa1]])
            if (x==ls[fa1]) rotate(fa1,2),rotate(x,2);
              else rotate(x,1),rotate(x,2);
          else 
            if (x==rs[fa1]) rotate(fa1,1),rotate(x,1);
              else rotate(x,2),rotate(x,1);
          fa1=fa[x];
        }
        if (!goal) root=x;
      }
      ll search(ll goal)
      {
        ll x=root;
        while (x)
        {
          if (vv[x]==goal) return(x);
          if (vv[x]<goal) x=rs[x];
          else x=ls[x];
        }
      }
      void ins(ll y,ll x1)
      {
        ll x=root;
        while (x)
        {
          if (y>vv[x])
            if (rs[x]) x=rs[x]; else break;
          else
            if (ls[x]) x=ls[x]; else break;
        }
        if (!x) root=++cnt;
        else
        {
          if (y>vv[x])
          {
            rs[x]=++cnt; fa[cnt]=x;
          } else
          {
            ls[x]=++cnt; fa[cnt]=x;
          }
        }
        vv[cnt]=y; v[cnt]=x1; count2[cnt]=1;
        splay(cnt,0);
      }
      void del(ll x1)
      {
        ll x=search(x1);
        splay(x,0);
        if (!ls[x])
        {
          root=rs[root]; fa[root]=0; return; 
        }
        ll y=ls[x];
        while (rs[y]) y=rs[y];
        rs[y]=rs[x];
        if (rs[y]) fa[rs[y]]=y;
        updata(y);
        root=ls[x]; fa[ls[x]]=0; splay(y,0);
      }
    }A,B;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      cl[0]=1;
      for (ll i=1;i<N;i++) cl[i]=(1ll*cl[i-1]*Base);
      cin>>n>>m>>q;
      ll cnt=0;
      for (ll i=0;i<m;i++) cnt+=cl[i];
      for (ll i=1;i<=n;i++) cin>>a[i];
      for (ll i=1;i<=m;i++) A.ins(a[i],i);
      ++M[A.data[A.root]];
      for (ll i=m+1;i<=n;i++)
      {
        A.del(a[i-m]); A.ins(a[i],i);
        ll tmp=A.data[A.root]-1ll*cnt*(i-m);
        ++M[tmp];
      }
      for (ll i=1;i<=m;i++)
      {
        cin>>b[i];
        B.ins(b[i],i);
      }
      for (ll i=1;i<=q;i++)
      {
        ll x,y;
        cin>>x>>y;
        B.del(b[x]);
        b[x]=y;
        B.ins(y,x);
        cout<<M[B.data[B.root]]<<endl;
      }
      return 0;
    }
  • 相关阅读:
    std::queue
    关于GridView中如何取得隐藏列的值
    揭秘史上最昂贵的一行Javascript代码
    CentOS 安装 git2.x.x 版本
    error: Some data has already been output, can't send PDF file
    接口和抽象类有什么区别
    php与apache的那些事
    PHP生成PDF完美支持中文,解决TCPDF乱码
    php 表单相关
    快速的去除数组中的指定值
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9256815.html
Copyright © 2020-2023  润新知