我怎么这么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; }