zoukankan      html  css  js  c++  java
  • [bzoj3282]Tree_LCT

    Tree bzoj-3282

    题目大意:给你n个点m个操作。更改单点权值,加边,删边;查询路径异或和。

    注释:$1le n,mle 10^5$

    想法:看到了加边删边,果断想到LCT维护。至于路径异或和,我们只需要维护每个点对应splay的子树异或和,然后查询的时候直接access+splay,makeroot之后就行了。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 300050
    #define ls ch[p][0]
    #define rs ch[p][1]
    #define get(x) (ch[f[x]][1]==x)
    int ch[N][2],f[N],sum[N],n,m,val[N],rev[N];
    inline bool isrt(int p)
    {
        return ch[f[p]][1]!=p&&ch[f[p]][0]!=p;
    }
    inline void pushdown(int p)
    {
        if(rev[p])
    	{
            swap(ch[ls][0],ch[ls][1]);
            swap(ch[rs][0],ch[rs][1]);
            rev[ls]^=1; rev[rs]^=1;
            rev[p]=0;
        }
    }
    inline void pushup(int p)
    {
        sum[p]=sum[ls]^sum[rs]^val[p];
    }
    inline void update(int p)
    {
        if(!isrt(p)) update(f[p]);
        pushdown(p);
    }
    void rotate(int x)
    {
        int y=f[x],z=f[y],k=get(x);
        if(!isrt(y)) ch[z][ch[z][1]==y]=x;
        ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
        ch[x][!k]=y; f[y]=x; f[x]=z;
        pushup(y); pushup(x);
    }
    void splay(int x)
    {
        update(x);
        for(int fa;fa=f[x],!isrt(x);rotate(x))
            if(!isrt(fa))
                rotate(get(fa)==get(x)?fa:x);
    }
    void access(int p)
    {
        int t=0;
        while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
    }
    void makeroot(int p)
    {
        access(p); splay(p);
        swap(ls,rs); rev[p]^=1;
    }
    void link(int x,int p)
    {
        makeroot(x); f[x]=p;
    }
    void cut(int x,int p)
    {
        makeroot(x); access(p); splay(p); ls=f[x]=0;
    }
    int find(int p)
    {
        access(p); splay(p);
        while(ls) pushdown(p),p=ls;
        return p;
    }
    void fix(int x,int v)
    {
        splay(x);
    	sum[x]^=val[x];
    	val[x]=v;
    	sum[x]^=val[x];
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int i,x,y,opt;
        for(i=1;i<=n;i++) scanf("%d",&val[i]);
        for(i=1;i<=m;i++)
    	{
            scanf("%d%d%d",&opt,&x,&y);
            if(opt==0)
    		{
                makeroot(x); access(y); splay(y);
                printf("%d
    ",sum[y]);
            }else if(opt==1)
    		{
                int t1=find(x),t2=find(y);
                if(t1!=t2) link(x,y);
            }else if(opt==2)
    		{
                int t1=find(x),t2=find(y);
                if(t1==t2) cut(x,y);
            }else
    		{
                fix(x,y);
            }
        }
    }
    

    小结:LCT的题有很明显的特点,就是动态维护加边删边,一般要是你能做上就上LCT吧,别的能维护动态树我也不会啊...

  • 相关阅读:
    使用CablleStatement调用存储过程
    权限问题
    全文检索lucene6.1的检索方式
    spring的JdbcTemplate
    spring使用注解开发
    IDEA的快捷键:
    IDEA里面的facets和artifacts的讲解
    Hibernate---criteria的具体使用列子
    关于操作日期函数及其取范围
    hibernate---crateria
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9315555.html
Copyright © 2011-2022 走看看