• BZOJ3282: Tree (LCT模板)


    Description

    给定N个点以及每个点的权值,要你处理接下来的M个操作。
    操作有4种。操作从0到3编号。点从1到N编号。
    0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。
    保证x到y是联通的。
    1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接。
    2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。
    3:后接两个整数(x,y),代表将点X上的权值变成Y。

    Input

    第1行两个整数,分别为N和M,代表点数和操作数。
    第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
    第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
    1<=N,M<=300000

    Output

    对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。

    Sample Input

    3 3
    1
    2
    3
    1 1 2
    0 1 2
    0 1 1

    Sample Output

    3
    1

    解题思路:

    这是LCT很好的模板。
    主要难点是处理一下路径权值,和判断两个点是否联通(以防重边)
    路径权值:单独将x到y的路径提取(split)Splay维护链的时候在将节点处权值上传,最后查值就好
    判断有无x到y的边:将x到y的路径提取,若直接连接无中间值就是有边。
    代码:
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll tr[spc].ch[0]
      5 #define rrr tr[spc].ch[1]
      6 #define ls ch[0]
      7 #define rs ch[1]
      8 const int N=200000;
      9 struct trnt{
     10     int ch[2];
     11     int lzt;
     12     int fa;
     13     int val;
     14     int sum;
     15     bool anc;
     16 }tr[N];
     17 int n,m;
     18 int cnt;
     19 bool whc(int spc)
     20 {
     21     return tr[tr[spc].fa].rs==spc;
     22 }
     23 void pushup(int spc)
     24 {
     25     tr[spc].sum=tr[lll].sum^tr[rrr].sum^tr[spc].val;
     26     return ;
     27 }
     28 void trr(int spc)
     29 {
     30     if(!spc)
     31         return ;
     32     std::swap(lll,rrr);
     33     tr[spc].lzt^=1;
     34     return ;
     35 }
     36 void pushdown(int spc)
     37 {
     38     if(tr[spc].lzt)
     39     {
     40         trr(lll);
     41         trr(rrr);
     42         tr[spc].lzt=0;
     43     }
     44     return ;
     45 }
     46 void recal(int spc)
     47 {
     48     if(!tr[spc].anc)
     49         recal(tr[spc].fa);
     50     pushdown(spc);
     51 }
     52 void rotate(int spc)
     53 {
     54     int f=tr[spc].fa;
     55     bool k=whc(spc);
     56     tr[f].ch[k]=tr[spc].ch[!k];
     57     tr[spc].ch[!k]=f;
     58     if(tr[f].anc)
     59     {
     60         tr[f].anc=false;
     61         tr[spc].anc=true;
     62     }else
     63         tr[tr[f].fa].ch[whc(f)]=spc;
     64     tr[spc].fa=tr[f].fa;
     65     tr[f].fa=spc;
     66     tr[tr[f].ch[k]].fa=f;
     67     pushup(f);
     68     pushup(spc);
     69 }
     70 void splay(int spc)
     71 {
     72     recal(spc);
     73     while(!tr[spc].anc)
     74     {
     75         int ft=tr[spc].fa;
     76         if(tr[ft].anc)
     77         {
     78             rotate(spc);
     79             return ;
     80         }
     81         if(whc(spc)^whc(ft))
     82             rotate(spc);
     83         else
     84             rotate(ft);
     85         rotate(spc);
     86     }
     87     return ;
     88 }
     89 void access(int spc)
     90 {
     91     int lsts=0;
     92     while(spc)
     93     {
     94         splay(spc);
     95         tr[rrr].anc=true;
     96         tr[lsts].anc=false;
     97         rrr=lsts;
     98         pushup(spc);
     99         lsts=spc;
    100         spc=tr[spc].fa;
    101     }
    102     return ;
    103 }
    104 void Mtr(int spc)
    105 {
    106     
    107     access(spc);
    108     splay(spc);
    109     trr(spc);
    110     return ;
    111 }
    112 int spmrt(int spc)
    113 {
    114     access(spc);
    115     splay(spc);
    116     while(lll)
    117     {
    118         pushdown(spc);
    119         spc=lll;
    120     }
    121     return spc;
    122 }
    123 void split(int x,int y)
    124 {
    125     Mtr(x);
    126     access(y);
    127     splay(y);
    128 }
    129 void Link(int x,int y)
    130 {
    131     Mtr(x);
    132     if(spmrt(y)!=x)
    133         tr[x].fa=y;
    134     return ;
    135 }
    136 void Cut(int x,int y)
    137 {
    138     Mtr(x);
    139     if(spmrt(y)==x&&tr[x].fa==y&&!tr[y].rs)
    140     {
    141         tr[x].anc=1;
    142         tr[y].ls=0;
    143         tr[x].fa=0;
    144         pushup(y);
    145     }
    146     return ;
    147 }
    148 int main()
    149 {
    150     scanf("%d%d",&n,&m);
    151     for(int i=1;i<=n;i++)
    152     {
    153         scanf("%d",&tr[i].val);
    154         tr[i].anc=true;
    155     }
    156     while(m--)
    157     {
    158         int cmd,x,y;
    159         scanf("%d%d%d",&cmd,&x,&y);
    160         if(cmd==0)
    161         {
    162             split(x,y);
    163             printf("%d
    ",tr[y].sum);
    164         }
    165         if(cmd==1)
    166             Link(x,y);
    167         if(cmd==2)
    168             Cut(x,y);
    169         if(cmd==3)
    170         {
    171             splay(x);
    172             tr[x].val=y;
    173             pushup(x);
    174         }
    175     }
    176     return 0;
    177 }
  • 相关阅读:
    171 01 Android 零基础入门 03 Java常用工具类02 Java包装类 01 包装类简介 01 Java包装类内容简介
    170 01 Android 零基础入门 03 Java常用工具类01 Java异常 08 Java异常总结 01 异常总结
    169 01 Android 零基础入门 03 Java常用工具类01 Java异常 07 异常链 01 异常链简介
    168 01 Android 零基础入门 03 Java常用工具类01 Java异常 06 自定义异常 01 自定义异常类
    167 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 02 使用throw抛出异常对象
    166 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 01 使用throws声明异常类型
    165 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 05 return关键字在异常处理中的使用
    DevExpress WPF v20.2版本亮点放送:全新升级的PDF Viewer
    界面控件DevExpress使用教程:Dashboard – 自定义导出
    DevExpress WinForms帮助文档:表单控件
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9638970.html
Copyright © 2020-2023  润新知