• 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 }
  • 相关阅读:
    MongoDB基础之五:游标
    SQLSERVER 中实现类似Mysql的 INSERT ON DUPLICATE KEY UPDATE
    统计C语言程序行数
    作业(一)
    无法获取有关Windows NT 组用户‘组用户’的信息,错误代码0x5(Microsoft SQL Server,错误:15404)
    DELETE与TRUNCATE的区别
    SQL Server显式事务与隐式事务
    SQL Server去掉字段内的双引号
    AlwaysOn与数据库镜像端点问题
    AlwaysOn数据同步暂停及回退技术
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9638970.html
Copyright © 2020-2023  润新知