bzoj2002(lct)

来源:互联网 发布:怎么注册淘宝云客服 编辑:程序博客网 时间:2024/04/25 15:32

算是自己做的第一个lct吧。

 

都是基本操作没有,练摸版了,不过lct当中也是有很多很灵活的地方。

 

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<stack>using namespace std;const int N=200005;inline int read(){int ans,f=1;char ch;while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';return ans*f;}int size[N],fa[N],ch[N][2],a[N];int n;bool rev[N];inline bool isroot(int u){return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u;}void up(int u){size[u]=size[ch[u][0]]+size[ch[u][1]]+1;}void down(int u){int l=ch[u][0],r=ch[u][1];if (rev[u]){rev[l]^=1;rev[r]^=1;rev[u]^=1;swap(ch[u][0],ch[u][1]);}}void rot(int x){int y=fa[x],z=fa[y],l,r;if (ch[y][0]==x) l=0;else l=1;r=l^1;if (!isroot(y))if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;ch[y][l]=ch[x][r];ch[x][r]=y;up(y);}stack<int> s;void splay(int x){int y=x,z;while (!isroot(y)) s.push(y),y=fa[y];s.push(y);while (!s.empty()) down(s.top()),s.pop(); while (!isroot(x)){y=fa[x],z=fa[y];if (!isroot(y))if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);rot(x);}up(x);}void access(int u){int t=0;while (u){splay(u);ch[u][1]=t;t=u;u=fa[u];}}void to_rt(int u){access(u);splay(u);rev[u]^=1;}void cut(int u,int v){to_rt(u);access(v);splay(v);fa[u]=ch[v][0]=0;}void link(int u,int v){to_rt(u);fa[u]=v;}void query(){int x=read()+1;//不管这个树是什么形态的,两点之间的边数肯定是一定的,而我们要求到表示外部的虚拟节点的步数,其实就可以把虚拟节点转到根,这样无论之前树是什么形态的就都无妨了。根据定义和性质access,splay之后当前节点左子树大小就是他上面的节点数也就是要走的步数to_rt(n+1);access(x);splay(x);printf("%d\n",size[ch[x][0]]);}void updata(){int pos=read()+1,x=read();cut(min(pos+a[pos],n+1),pos);//link(pos,min(pos+x,n+1));//注意虚拟节点,pos+a[pos]可能就已经跳出了序列了,注意细节!a[pos]=x;}int main(){n=read();int x,op;for (int i=1;i<=n;i++){x=read();link(i,min(i+x,n+1));//虚拟一个节点表示外界,连到这个点的边表示跳出了序列当中。a[i]=x;}int m=read();while (m--){op=read();if (op==1) query();else updata();}return 0;}


总结

1:lct的操作和维护方法还是要多积累,要善于利用access等性质。

2:在一些线性的题目中,一些位置都有一个唯一后继或,唯一前驱,顺着这些前驱信息,这样就是可以构成一颗树结构了,并成功的将数列问题转化成了树的问题,并且根据树的一些性质,还可以将题目进行优化(见过的有树上倍增(某年noip开车旅行),lct(本题)等)。

0 0