题解:

的确是动态树好题

首先由于每个点只有一个出边

这个图构成了基环内向树

我们观察那个同余方程组

一旦形成环的话我们就能知道环上点以及能连向环上点的值是多少了

所以我们只需要用一种结构来维护两个不是直接相连点的状态

由于有删边连边操作,比较容易想到lct

我们按照套路将它拆掉一条边形成一颗树

因为我们现在只知道环上某一点的值,所以我们这棵树应该是不随便换根的

每次询问只需要把当前这个点access再splay一下 查询用根怎么表示就可以了

修改方程组等价于删一条边,连一条边

删的边如果不在环上 直接删

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for(int i=h;i<=t;i++)
#define dep(i,t,h) for(int i=t;i>=h;i--)
#define ll long long
#define me(x) memset(x,0,sizeof(x))
#define mep(x,y) memcpy(x,y,sizeof(y))
#define mid ((h+t)>>1)
namespace IO{
char ss[<<],*A=ss,*B=ss;
IL char gc()
{
return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;
}
template<class T> void read(T &x)
{
rint f=,c; while (c=gc(),c<||c>) if (c=='-') f=-; x=(c^);
while (c=gc(),c>&&c<) x=(x<<)+(x<<)+(c^); x*=f;
}
template<class T>void read2(T &x)
{
rint c;
while (c=gc(),c!='A'&&c!='C'); x=c;
}
char sr[<<],z[]; ll Z,C1=-;
template<class T>void wer(T x)
{
if (x<) sr[++C1]='-',x=-x;
while (z[++Z]=x%+,x/=);
while (sr[++C1]=z[Z],--Z);
}
IL void wer1()
{
sr[++C1]=' ';
}
IL void wer2()
{
sr[++C1]='\n';
}
template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
template<class T>IL T MAX(T x,T y){return x>y?x:y;}
template<class T>IL T MIN(T x,T y){return x<y?x:y;}
};
const int N=5e4;
int k[N],p[N],b[N];
const int mo=;
struct re{
int a,b;
re operator *(const re o) const
{
re c;
c.a=a*o.a%mo; c.b=(o.a*b+o.b)%mo;
return c;
}
};
IL int fsp(int x,int y)
{
int now=;
while (y)
{
if (y&) now=now*x%mo;
x=x*x%mo; y>>=;
}
return now;
}
struct lct{
int ls[N],fa[N],rs[N],sp[N],ans[N];
re sum[N],v[N];
IL void updata(int x)
{
if (ls[x]) sum[x]=sum[ls[x]]*v[x];
else sum[x]=v[x];
if (rs[x]) sum[x]=sum[x]*sum[rs[x]];
}
IL bool pd(int x)
{
return ls[fa[x]]==x||rs[fa[x]]==x;
}
void rotate(int x,int y)
{
int f1=fa[x];
if (y==)
{
rs[f1]=ls[x];
if (ls[x]) fa[ls[x]]=f1;
} else
{
ls[f1]=rs[x];
if (rs[x]) fa[rs[x]]=f1;
}
fa[x]=fa[f1];
if (pd(f1))
{
if (ls[fa[f1]]==f1) ls[fa[f1]]=x;
else rs[fa[f1]]=x;
}
if (y==) ls[x]=f1; else rs[x]=f1;
fa[f1]=x;
updata(f1); updata(x);
}
void splay(int x)
{
// dfs(x);
int f1=fa[x];
while (pd(x))
{
if (!pd(f1))
{
if (ls[f1]==x) rotate(x,); else rotate(x,);
} else
if (ls[fa[f1]]==f1)
if (ls[f1]==x) rotate(f1,),rotate(x,);
else rotate(x,),rotate(x,);
else
if (rs[f1]==x) rotate(f1,),rotate(x,);
else rotate(x,),rotate(x,);
f1=fa[x];
}
}
void access(int x)
{
for (int y=;x;y=x,x=fa[x])
{
splay(x); rs[x]=y; updata(x);
}
}
int fdr(int x)
{
access(x); splay(x);
while (ls[x]) x=ls[x];
return x;
}
int query(int x)
{
access(x); splay(x);
int ro=fdr(x);
re kk=sum[x];
access(sp[ro]);
splay(sp[ro]);
int ans,a=sum[sp[ro]].a,b=sum[sp[ro]].b;
if (a==)
if (b==) ans=-; else ans=-;
ans=(fsp((-a),mo-)*b%mo+mo)%mo;
if (ans==-) return(-);
if (ans==-) return(-);
return ((ans*kk.a+kk.b)%mo+mo)%mo;
}
IL void cut(int x)
{
access(x); splay(x); ls[x]=fa[ls[x]]=; updata(x);
}
void change(int x,int k,int p,int b)
{
int rt=fdr(x);
if (x==rt)
{
if (fdr(p)!=x)
{
sp[x]=; fa[x]=p;
} else
{
sp[x]=p;
}
} else
{
access(sp[rt]); splay(sp[rt]);
int z=x;
while (pd(z)) z=fa[z];
if (z==sp[rt])
{
cut(x);
access(rt); splay(rt); fa[rt]=sp[rt]; sp[rt]=;
} else
{
cut(x);
}
if (fdr(p)!=x)
{
fa[x]=p;
} else
{
sp[x]=p;
}
}
v[x]=(re){k,b}; splay(x);
}
IL void link(int x,int y)
{
if (fdr(x)!=fdr(y))
{
fa[x]=y;
} else sp[x]=y;
}
}S;
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
int n;
IO::read(n);
rep(i,,n)
{
IO::read(k[i]),IO::read(p[i]),IO::read(b[i]);
S.v[i]=(re){k[i],b[i]};
S.link(i,p[i]);
}
int q;
IO::read(q);
rep(i,,q)
{
char c;
IO::read2(c);
if (c=='A')
{
int a;
IO::read(a);
IO::wer(S.query(a)); IO::wer2();
} else
{
int a,b,c,d;
IO::read(a); IO::read(b); IO::read(c); IO::read(d);
S.change(a,b,c,d);
}
}
fwrite(IO::sr,,IO::C1+,stdout);
return ;
}

删的边如果在环上 并且没有连上 把标记清除

删的边如果在环上 并且连上了 把这条边段删了,然后把标记边连上

BZOJ2759 一个动态树好题 LCT的更多相关文章

  1. BZOJ2759一个动态树好题 LCT

    题如其名啊 昨天晚上写了一发忘保存 只好今天又码一遍了 将题目中怕$p[i]$看做$i$的$father$ 可以发现每个联通块都是一个基环树 我们对每个基环删掉环上一条边 就可以得到一个森林了 可以用 ...

  2. BZOJ2759: 一个动态树好题

    BZOJ2759: 一个动态树好题 Description 有N个未知数x[1..n]和N个等式组成的同余方程组:x[i]=k[i]*x[p[i]]+b[i] mod 10007其中,k[i],b[i ...

  3. BZOJ 2759 一个动态树好题 (LCT)

    PoPoQQQ 再一次orz-没看得特别明白的可以回来看看蒟蒻的补充口胡 我这里提一下关于splaysplaysplay维护的子树信息- 在原树上考虑,对于每一个点iii都有这样一个信息xi=ki∗x ...

  4. [BZOJ 2759] 一个动态树好题

    [BZOJ 2759] 一个动态树好题 题目描述 首先这是个基环树. 然后根节点一定会连出去一条非树边.通过一个环就可以解除根的答案,然后其他节点的答案就可以由根解出来. 因为要修改\(p_i\),所 ...

  5. bzoj 2759一个动态树好题

    真的是动态树好题,如果把每个点的父亲设成p[x],那么建出来图应该是一个环套树森林,拆掉一条边,就变成了动态树,考虑维护什么,对于LCT上每个节点,维护两组k和b,一组是他到他父亲的,一组是他LCT子 ...

  6. 【bzoj2759】一个动态树好题

    Portal -->bzoj2759 Solution 哇我感觉这题真的qwq是很好的一题呀qwq 很神qwq反正我真的是自己想怎么想都想不到就是了qwq 首先先考虑一下简化版的问题应该怎么解决 ...

  7. 【刷题】BZOJ 2759 一个动态树好题

    Description 有N个未知数x[1..n]和N个等式组成的同余方程组: x[i]=k[i]*x[p[i]]+b[i] mod 10007 其中,k[i],b[i],x[i]∈[0,10007) ...

  8. BZOJ 2759 一个动态树好题(动态树)

    题意 https://www.lydsy.com/JudgeOnline/problem.php?id=2759 思路 每个节点仅有一条有向出边, 这便是一棵基环内向树,我们可以把它在 \(\text ...

  9. 动态树Link-cut tree(LCT)总结

    动态树是个好玩的东西 LCT题集 预备知识 Splay 树链剖分(好像关系并不大) 动态树(Link-cut tree) 先搬dalao博客 什么是LCT? 动态树是一类要求维护森林的连通性的题的总称 ...

随机推荐

  1. [HNOI2007]神奇游乐园(插头DP)

    题意:n*m的矩阵内值有正有负,找一个四连通的简单环(长度>=4),使得环上值的和最大. 题解:看到2<=m<=6和简单环,很容易想到插头DP,设f[i][j][k]表示轮廓线为第i ...

  2. 关于 redis 的 数据类型 和 内存模型

    该文章 是在读了 公众号 : java 后端技术 之后 做的一个小记录 原文网址  : https://mp.weixin.qq.com/s/mI3nDtQdlVlLv2uUTxJegA 作者文章写的 ...

  3. textCNN原理

    一.TextCnn的结构 1. 嵌入层(embedding layer) textcnn使用预先训练好的词向量作embedding layer.对于数据集里的所有词,因为每个词都可以表征成一个向量,因 ...

  4. [源码分析]ReentrantLock & AbstractQueuedSynchronizer & Condition

    首先声明一点: 我在分析源码的时候, 把jdk源码复制出来进行中文的注释, 有时还进行编译调试什么的, 为了避免和jdk原生的类混淆, 我在类前面加了"My". 比如把Reentr ...

  5. vscode中文配置说明

    1.官网下载vscode安装完毕后, 2.在扩展中搜索chinese,选择:“Chinese (Simplified) Language Pack for Visual Studio Code” 3. ...

  6. EF Code First关系规则及配置

    1.一对多关系 关系表: Category 分类表 Product 产品表 分类与产品之间的一对多关系 1>.产品实体类不指定外键属性 Domain中类定义: Category.cs 1 usi ...

  7. 你真的了解word-wrap和word-break的区别吗?

    这两个东西是什么,我相信至今还有很多人搞不清,只会死记硬背的写一个word-wrap:break-word;word-break:break-all;这样的东西来强制断句,又或者是因为这两个东西实在是 ...

  8. sorted

    排序是编程中经常使用到的算法,无论哪种排序算法, 本质上都是比较两个元素的大小.如果是数字,可以直接比较,但是如果是字符串或者是dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函 ...

  9. 基于Python的Webservice开发(二)-如何用Spyne开发Webservice

    一.功能需求 本次案例是开发一个Item的新建的WebService.IN&OUT的类型JsonDocument. 通过传入相关的参数创建Item,且相关的参数可以被缺省. 二.实现代码 引入 ...

  10. 机器学习基石11-Linear Models for Classification

    注: 文章中所有的图片均来自台湾大学林轩田<机器学习基石>课程. 笔记原作者:红色石头 微信公众号:AI有道 上一节课,我们介绍了Logistic Regression问题,建立cross ...