• uoj207 共价大爷游长沙


    题意:动态树上支持加入路径、删除路径、询问一条边是否被当时存在的所有路径经过?

    标程:

     1 #include<bits/stdc++.h>
     2 #define P pair<int,int>
     3 using namespace std;
     4 int read()
     5 {
     6     int x=0;char ch=getchar();
     7     while (ch<'0'||ch>'9') ch=getchar();
     8     while ('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
     9     return x;
    10 }
    11 const int N=300005;
    12 P e[N];
    13 int son[N][2],fa[N],top,q[N],rev[N],sum[N],lsum[N],val[N],n,Q,x,y,op,w[N],u,v,cnt,s;
    14 bool is_rt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
    15 void up(int x)
    16 {
    17     sum[x]=val[x]^lsum[x];
    18     sum[x]^=sum[son[x][0]]^sum[son[x][1]]; 
    19 }
    20 void down(int x)
    21 {
    22     if (rev[x]) 
    23     {
    24         rev[son[x][0]]^=1;rev[son[x][1]]^=1;rev[x]^=1;
    25         swap(son[x][0],son[x][1]);
    26     }
    27 }
    28 void rot(int x)
    29 {
    30     int y=fa[x],z=fa[y],l=(son[y][1]==x),r=l^1;
    31     if (!is_rt(y)) son[z][son[z][1]==y]=x;
    32     fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
    33     son[y][l]=son[x][r];son[x][r]=y;
    34     up(y);up(x);
    35 }
    36 void spl(int x)
    37 {
    38     q[top=1]=x;
    39     for (int i=x;!is_rt(i);i=fa[i]) q[++top]=fa[i];
    40     while (top) down(q[top--]);
    41     for (int y;!is_rt(x);rot(x))//注意这里的y要在内部定义,否则会更改掉外面的y 
    42     {
    43         if (!is_rt(y=fa[x]))
    44           rot(((son[y][0]==x)^(son[fa[y]][0]==y))?x:y); 
    45     }
    46 }
    47 void accs(int x) {
    48     for (int t=0;x;t=x,x=fa[x]) 
    49     {
    50         spl(x);
    51         lsum[x]^=sum[son[x][1]];//原来的重儿子变成轻儿子,加入 
    52         lsum[x]^=sum[son[x][1]=t];//去掉原来的轻儿子 
    53         up(x);    
    54     }
    55 }
    56 void make_rt(int x) {accs(x);spl(x);rev[x]^=1;}
    57 void cut(int x,int y){make_rt(x);accs(y);spl(y);fa[x]=son[y][0]=0;up(y);}
    58 void link(int x,int y){make_rt(x);fa[x]=y;make_rt(y);lsum[y]^=sum[x];up(y);}
    59 void mdi(int x,int v) {make_rt(x);val[x]^=v;up(x);}
    60 int main()
    61 {
    62     int id=read();srand(time(NULL));
    63     n=read();Q=read();
    64     for (int i=1;i<n;i++) u=read(),v=read(),link(u,v);
    65     while (Q--)
    66     {
    67         op=read();
    68         if (op==1)
    69         {
    70             x=read();y=read();cut(x,y);
    71             x=read();y=read();link(x,y); 
    72         }else if (op==2){
    73             x=read();y=read();w[++cnt]=rand()*131;
    74             mdi(x,w[cnt]);mdi(y,w[cnt]);
    75             s^=w[cnt];e[cnt]=P(x,y);
    76         }else if (op==3) {
    77             x=read();s^=w[x];
    78             mdi(e[x].first,w[x]);mdi(e[x].second,w[x]);
    79         }
    80         else {
    81             x=read();y=read();
    82             make_rt(x);accs(y);spl(y);
    83             puts(sum[x]==s?"YES":"NO");
    84         }
    85     }
    86     return 0;
    87 } 
    View Code

    题解:lct+随机权值

    对每条路径随机一个权值,并在两端点处赋值。

    询问时如果子树中的权值异或和=所有路径的异或和,那么大概率(x,y)这条边被所有路径经过。

    sum表示整个子树的异或和,lsum表示轻儿子子树的异或和。由于重儿子在lct上会不断改变,而lsum只有在accs重连和link时会被改变。

    link时修改lsum[y],需要make_rt(y),不然需要改变y到根的链上所有点的sum。

  • 相关阅读:
    使用sublimehighlight 将文本 转化html
    iOS- 制作U盘安装Mac OS X 系统
    Win10 UWP vs add github
    Win10 Migrate apps to the Universal Windows Platform (UWP)
    lintcode 刷题记录··
    C# 用tabcontrol实现窗体类似网页排版的显示
    python 爬虫初试
    二叉查找树,查找二维数组
    网页版扫雷游戏···
    C# 读写xml、excel、word、ppt、access
  • 原文地址:https://www.cnblogs.com/Scx117/p/9144609.html
Copyright © 2020-2023  润新知