[BZOJ3282]LCT模板(单点修改,区间查询)

来源:互联网 发布:c语言程序实例代码 编辑:程序博客网 时间:2024/06/14 21:58

题目:

我是超链接

题解:

这就是LCT的裸题啦,单点修改啦,区间查询xor啦,都是比较简单的操作
单点修改直接修改就好啦,然后access一下,从下面到上面的access最适合我们update值了,那就在access里面update几次?
区间查询在update里面搞点事情就行
后面有小总结啦

代码:

#include <cstdio>#include <iostream>using namespace std;const int N=300005;int ch[N][2],xo[N],delta[N],f[N],stack[N],key[N];int get(int x){return ch[f[x]][1]==x;}void updata(int x){xo[x]=xo[ch[x][0]]^xo[ch[x][1]]^key[x];}void pushdown(int x){    if(delta[x])    {        swap(ch[x][0],ch[x][1]);        delta[ch[x][0]]^=1; delta[ch[x][1]]^=1;        delta[x]=0;    }}bool Is_root(int x){return ch[f[x]][0]!=x && ch[f[x]][1]!=x;}void rotate(int x){    int old=f[x],oldf=f[old],which=get(x),gen=Is_root(old);    ch[old][which]=ch[x][which^1]; f[ch[x][which^1]]=old;    f[old]=x; ch[x][which^1]=old;    f[x]=oldf; if (!gen) ch[oldf][ch[oldf][1]==old]=x;    updata(old);    updata(x);}void splay(int x){    int top=0,i;    for (i=x;!Is_root(i);i=f[i]) stack[++top]=i;    stack[++top]=i;    for (i=top;i>=1;i--) pushdown(stack[i]);    for (;!Is_root(x);rotate(x))      if (!Is_root(f[x])) rotate(get(f[x])==get(x)?f[x]:x);}void access(int x){    int t=0;    for (;x;t=x,x=f[x])    {        splay(x);        ch[x][1]=t;        updata(x);    }}void reverse(int x){    access(x);    splay(x);    delta[x]^=1;}int find(int x){    int now=x;    while (ch[now][0]) now=ch[now][0];    return now;}bool connect(int x,int y){    access(x); splay(x);    int fa1=find(x);    access(y); splay(y);    int fa2=find(y);    if (fa1==fa2) return 1;    return 0;}void Link(int x,int y){    if (connect(x,y)) return;    reverse(x);    f[x]=y;    splay(x);}void Cut(int x,int y){    if (!connect(x,y)) return;    reverse(x);    access(y);    splay(y);    ch[y][0]=f[x]=0;}int qurry(int x,int y){    reverse(x);    access(y);    splay(y);    return xo[y];}int main(){    int n,m,i,id;    scanf("%d%d",&n,&m);    for (i=1;i<=n;i++) scanf("%d",&key[i]);    while (m--)    {        int x,y;        scanf("%d%d%d",&id,&x,&y);        if (id==0) printf("%d\n",qurry(x,y));        else if (id==1) Link(x,y);        else if (id==2) Cut(x,y);        else {key[x]=y; access(x);}    }}

tip:

在区间里查询值的做法:把一个端点reverse到根,然后把另一个端点access+splay到顶点,这时候顶点维护的值就是我们要的值,因为不属于这个区间内的点(也就是不属于这条链上的)根本就不是这棵splay的儿子,值根本不会被记录进去

阅读全文
1 0