我怎么这么shabi

块状链表,首先看错题,之后手残打错字母....

题目介绍上写的是splay启发式合并,身为蒟蒻的我怎么能会这么高端的数据结构呢,于是学习了静态的块状链表。

挺好想的,将整个数组分为sqrt(n)块,预处理将每个点指向下一块的对应点,记录中间经过多少点,修改只需在单块内修改,查找每次最多将sqrt(n)块每个找一次,是链表与数组的杂交体。

代码凌乱:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,m;
int bl[200011]={},f[200011]={},to[200011]={};
int k[200011]={};
void init()
{
     scanf("%d",&n);
     int i,sq,r;sq=int(sqrt(n));
     int o=sq,t=0;
     for (i=0;i<n;i++)
     {
         if (o==sq)
         {
             bl[i]=++t;
             o=1;
         }
         else bl[i]=t,o++;
         scanf("%d",&f[i]);
         f[i]+=i;
     }
     for (i=n-1;i>=0;i--)
     {
         r=f[i];
         if (bl[r]!=bl[i]||r>=n) to[i]=r,k[i]=1;
         else
         {
             to[i]=to[r];k[i]=k[r]+1;
         }
     }
}
inline int ask(int x)
{
    int he=0;
    while (x<n)
    {
          he+=k[x];x=to[x];
    }
    return he;
}
inline void change(int x,int y)
{
     int i,j=bl[x],r;
     f[x]=y;r=y;
     if (bl[r]==bl[x]) to[x]=to[r],k[x]=k[r]+1;
     else to[x]=y,k[x]=1;
     for (i=x-1;i>=0;i--)
     {
         if (bl[i]!=j) break;
         r=f[i];
         if (bl[r]==bl[i]&&r<n) to[i]=to[r],k[i]=k[r]+1;
         else to[i]=r,k[i]=1;
     }
}
          
int main()
{
    init();
    int i,j,aa,bb,cc;
    scanf("%d",&m);
    while (m--)
    {
          scanf("%d",&aa);
          if (aa==1)
          {
                    scanf("%d",&bb);
                    printf("%d\n",ask(bb));
          }
          else
          {
              scanf("%d%d",&bb,&cc);
              cc+=bb;change(bb,cc);
          }
    }
    return 0;
}

​
View Code