• 模板Link Cut Tree (动态树)


    题目描述

    给定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。

    输入输出格式

    输入格式:

    第1行两个整数,分别为N和M,代表点数和操作数。

    第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。

    第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    3 3 
    1
    2
    3
    1 1 2
    0 1 2 
    0 1 1
    输出样例#1: 复制
    3
    1
    

    说明

    数据范围: 1≤N,M≤3⋅105

    算法原理提供可靠网址:

    zyys

    这道题用到的技巧:

    找根:$makeroot(o)$后一直往左走。最后一个节点就是根。(理由:由于$LCT$中$splay$的性质:按深度作为键值);

    判断是否之间有边:再$cut$之前,判断根的左儿子是否是另外一个点。(理由:若存在边,则包含这条边的$splay$只有两个节点)。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 #include<queue>
      7 using namespace std;
      8 int xr[300005],ch[300005][2],val[300005],pre[300005],n,m;
      9 bool isrt[300005],rev[300005];
     10 void pushup(int o)
     11 {
     12   if (!o) return;
     13   xr[o]=xr[ch[o][0]]^xr[ch[o][1]]^val[o];
     14 }
     15 void pushdown(int o)
     16 {
     17   if (!o) return;
     18   if (rev[o])
     19     {
     20       int ls=ch[o][0],rs=ch[o][1];
     21       if (ls)
     22     {
     23       rev[ls]^=1;
     24       swap(ch[ls][0],ch[ls][1]);
     25     }
     26       if (rs)
     27     {
     28       rev[rs]^=1;
     29       swap(ch[rs][0],ch[rs][1]);
     30     }
     31       rev[o]=0;
     32     }
     33 }
     34 void push(int o)
     35 {
     36   if (isrt[o]==0)
     37       push(pre[o]);
     38   pushdown(o);
     39 }
     40 void rotate(int o,bool kind)
     41 {
     42   int p=pre[o];
     43   ch[p][!kind]=ch[o][kind];pre[ch[o][kind]]=p;
     44   if (isrt[p]) isrt[o]=1,isrt[p]=0;
     45   else ch[pre[p]][ch[pre[p]][1]==p]=o;
     46   pre[o]=pre[p];
     47   ch[o][kind]=p;pre[p]=o;
     48   pushup(p);pushup(o);
     49 }
     50 void splay(int o)
     51 {
     52   push(o);
     53   while (isrt[o]==0)
     54     {
     55       if (isrt[pre[o]])
     56     rotate(o,ch[pre[o]][0]==o);
     57       else
     58     {
     59       int p=pre[o],kind=ch[pre[p]][0]==p;
     60       if (ch[p][kind]==o)
     61         rotate(o,!kind),rotate(o,kind);
     62       else rotate(p,kind),rotate(o,kind);
     63     }
     64     }
     65 }
     66 void access(int o)
     67 {
     68   int y=0;
     69   while (o)
     70     {
     71       splay(o);
     72       //xr[o]^=xr[ch[o][1]];
     73       isrt[ch[o][1]]=1;isrt[ch[o][1]=y]=0;
     74       pushup(o);
     75       o=pre[y=o];
     76     }
     77 }
     78 void makeroot(int o)
     79 {
     80   access(o);
     81   splay(o);
     82   rev[o]^=1;
     83   swap(ch[o][0],ch[o][1]);
     84 }
     85 int find(int o)
     86 {
     87   makeroot(o);
     88   access(o);splay(o);
     89   while (ch[o][0])
     90     {
     91       o=ch[o][0];
     92     }
     93   return o;
     94 }
     95 void link(int x,int y)
     96 {
     97   makeroot(x);
     98   pre[x]=y;
     99 }
    100 void cut(int x,int y)
    101 {
    102   makeroot(x);access(y);splay(y);
    103   if (ch[y][0]!=x) return;
    104   pre[x]=0;
    105   ch[y][0]=0;
    106   isrt[x]=1;
    107   pushup(y);
    108 }
    109 int main()
    110 {int i,c,x,y;
    111   cin>>n>>m;
    112   for (i=1;i<=n;i++)
    113     {
    114       scanf("%d",&val[i]);
    115       xr[i]=val[i];isrt[i]=1;
    116     }
    117   for (i=1;i<=m;i++)
    118     {
    119       scanf("%d%d%d",&c,&x,&y);
    120       if (c==0)
    121     {
    122       makeroot(y);
    123       access(x);
    124       splay(x);
    125       printf("%d
    ",xr[x]);
    126     }
    127       else if (c==1)
    128     {
    129       int p=find(x),q=find(y);
    130       if (p!=q) link(x,y);
    131     }
    132       else if (c==2)
    133     {
    134       cut(x,y);
    135     }
    136       else if (c==3)
    137     {
    138       val[x]=y;
    139       makeroot(x);
    140       pushup(x);
    141     }
    142     }
    143 }
  • 相关阅读:
    C#异步编程
    ASP.NET MVC5中View-Controller间数据的传递
    Dapper简明教程
    .NET中使用NLog记录日志
    微信开发被动回复消息:该公众号暂时无法提供服务,请稍后再试
    使用AutoMapper进行对象间映射
    Cookie中的几个概念
    使用CodeFirst创建并更新数据库
    restful接口设计规范总结
    JAVA中通过Hibernate-Validation进行参数验证
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8296329.html
Copyright © 2020-2023  润新知