BZOJ2759一个动态树好题 LCT
题如其名啊
昨天晚上写了一发忘保存 只好今天又码一遍了
将题目中怕\(p[i]\)看做\(i\)的\(father\) 可以发现每个联通块都是一个基环树 我们对每个基环删掉环上一条边 就可以得到一个森林了 可以用\(LCT\)维护
这时我们思考如何求解 对于一个环 拆掉边\((u,fa[u])\)得到一条链\((\)下令\(v=fa[u])\)我们通过关系是从链头\(u\)向下递推 在\(v\)点可以得到 \(x_v=k_1x_u+b_1\) 由删掉的\((u,v)\)边可得关系式 \(x_u=k_2x_v+b_2\) 带入\(x_u\)即可解得\(x_v\) 由于u是链头 所以也是联通块所在树的根 那么树上每个节点都可以从u递推得到形如\(x_i=k_ix_v+b_i\)的式子 带入\(x_v\)即可
实现时的难点在于基环上删除边的操作\((u,v\)同上\()\) 可以对于\(u\)记录$sfa[u]=v $ 每次修改\(x\)父亲为\(y\)时 通过求出\(sfa\)具体讨论\(x\)在环上还是环外 与\(y\)连边后构成环还是维持树结构 分类讨论并维护 具体的可以看代码的修改操作
#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 10007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi first
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
const int INF = 0x7fffffff;
const int N=3e4+5;
/*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
int x=0,rev=0,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return rev?-x:x;
}
struct data{
int k,b;
data(){k=1,b=0;}
data(int k,int b):k(k),b(b){}
int calc(int x){return (k*x+b)%mod;}
data operator +(const data&a) {return data(k*a.k%mod,(b*a.k%mod+a.b)%mod);}
};
int n;
char s[15];
void exgcd(int a,int b,int&x,int&y){
if(!b) x=1,y=0;
else exgcd(b,a%b,y,x),y-=a/b*x;
}
#define isroot(x) (c[fa[x]][0]!=x&&c[fa[x]][1]!=x)
struct LinkCutTree{
int c[N][2],fa[N],sfa[N];
data val[N],sum[N];
bool vis[N],ins[N];
void dfs(int x){
ins[x]=vis[x]=1;
int y=fa[x];
if(ins[y]) fa[x]=0,sfa[x]=y;
if(!vis[y]) dfs(y);
ins[x]=0;
}
void update(int x){
sum[x]=sum[c[x][0]]+val[x]+sum[c[x][1]];
}
void init(){
for(int i=1,k,b;i<=n;i++) k=read(),fa[i]=read(),b=read(),val[i]=sum[i]=data(k,b);
for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
}
void rotate(int x){
int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
if(!isroot(y)) c[z][c[z][1]==y]=x;
fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
c[y][l]=c[x][r],c[x][r]=y;
update(y),update(x);
}
void splay(int x){
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)) (c[z][0]==y^c[y][0]==x)?rotate(x):rotate(y);
rotate(x);
}
}
void access(int x){
for(int t=0;x;c[x][1]=t,update(x),t=x,x=fa[x]) splay(x);
}
int find(int x){
access(x),splay(x);
while(c[x][0]) x=c[x][0];
splay(x);
return x;
}
int Query(int x){
access(x),splay(x);
data v1=sum[x];
int rt=find(x),rtf=sfa[rt];
access(rtf),splay(rtf);
data v2=sum[rtf];
if(v2.k==1) return v2.b?-1:-2;
if(v2.k==0) return v1.calc(v2.b);
int xx,y;
exgcd(v2.k-1,mod,xx,y);
return v1.calc((mod-xx)%mod*v2.b%mod);
}
void cut(int x){
access(x),splay(x),fa[c[x][0]]=0,c[x][0]=0,update(x);
}
void link(int x,int y){
access(x),splay(x),fa[x]=y;
}
bool judge(int x,int rt){
int rtf=sfa[rt];
if(x==rtf) return 1;
access(rtf),splay(rtf),splay(x);
return !isroot(rtf);
}
void modify(int x,int y,int k,int b){
access(x),splay(x),val[x]=data(k,b),update(x);
int rt=find(x);
if(x==rt){
int rtf=find(y);
if(rtf==rt) sfa[x]=y;
else sfa[x]=0,link(x,y);
}
else{
if(judge(x,rt)) cut(x),link(rt,sfa[rt]),sfa[rt]=0;
else cut(x);
int rtf=find(y);
if(rtf==x) sfa[x]=y;
else link(x,y);
}
}
}lct;
int main(){
#ifdef Devil_Gary
freopen("in.txt","r",stdin);
#endif
n=read(),lct.init();
for(int Q=read(),k,f,b,x;Q;Q--){
scanf("%s",s),x=read();
if(s[0]=='A') printf("%d\n",lct.Query(x));
else k=read(),f=read(),b=read(),lct.modify(x,f,k,b);
}
}
BZOJ2759一个动态树好题 LCT的更多相关文章
- BZOJ2759 一个动态树好题 LCT
题解: 的确是动态树好题 首先由于每个点只有一个出边 这个图构成了基环内向树 我们观察那个同余方程组 一旦形成环的话我们就能知道环上点以及能连向环上点的值是多少了 所以我们只需要用一种结构来维护两个不 ...
- BZOJ2759: 一个动态树好题
BZOJ2759: 一个动态树好题 Description 有N个未知数x[1..n]和N个等式组成的同余方程组:x[i]=k[i]*x[p[i]]+b[i] mod 10007其中,k[i],b[i ...
- BZOJ 2759 一个动态树好题 (LCT)
PoPoQQQ 再一次orz-没看得特别明白的可以回来看看蒟蒻的补充口胡 我这里提一下关于splaysplaysplay维护的子树信息- 在原树上考虑,对于每一个点iii都有这样一个信息xi=ki∗x ...
- [BZOJ 2759] 一个动态树好题
[BZOJ 2759] 一个动态树好题 题目描述 首先这是个基环树. 然后根节点一定会连出去一条非树边.通过一个环就可以解除根的答案,然后其他节点的答案就可以由根解出来. 因为要修改\(p_i\),所 ...
- bzoj 2759一个动态树好题
真的是动态树好题,如果把每个点的父亲设成p[x],那么建出来图应该是一个环套树森林,拆掉一条边,就变成了动态树,考虑维护什么,对于LCT上每个节点,维护两组k和b,一组是他到他父亲的,一组是他LCT子 ...
- 【bzoj2759】一个动态树好题
Portal -->bzoj2759 Solution 哇我感觉这题真的qwq是很好的一题呀qwq 很神qwq反正我真的是自己想怎么想都想不到就是了qwq 首先先考虑一下简化版的问题应该怎么解决 ...
- 【刷题】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) ...
- BZOJ 2759 一个动态树好题(动态树)
题意 https://www.lydsy.com/JudgeOnline/problem.php?id=2759 思路 每个节点仅有一条有向出边, 这便是一棵基环内向树,我们可以把它在 \(\text ...
- 动态树Link-cut tree(LCT)总结
动态树是个好玩的东西 LCT题集 预备知识 Splay 树链剖分(好像关系并不大) 动态树(Link-cut tree) 先搬dalao博客 什么是LCT? 动态树是一类要求维护森林的连通性的题的总称 ...
随机推荐
- 研究slatstack时踩过的坑,注意点及解决方案
运行问题 1.直接物理性移除minion或者更换minion原先连接的master,会导致先前的master始终无法ping通minion [root@localhost salt]# salt '* ...
- 53环境Jenkins新增工程配置
1. 登录http://10.179.175.53:8080/环境. 2. 点击新建任务,输入任务名称,并在复制一个NOS的类似工程即可. 3. 在配置页面,修改源码地址: 4. 点击完成,执行构建, ...
- iframe传递参数问题
在页面中嵌入了iframe,如果需要传递参数到iframe中 1.通过将参数嵌入到url中,在iframe中使用${param.xxx}可以获取 2.通过将参数存入到session中,在iframe中 ...
- sqlserver循环
普通while循环 1 循环5来修改学生信息 循环遍历修改记录 DECLARE @i int set @i=0 while @i<5 BEGIN update Student set demo ...
- 解析神奇的 Object.defineProperty
这个方法了不起啊..vue.js是通过它实现双向绑定的..而且Object.observe也被草案发起人撤回了..所以defineProperty更有必要了解一下了. 几行代码看他怎么用 var a= ...
- ubuntu 电源管理
https://www.cnblogs.com/sky-heaven/p/4561374.html?tdsourcetag=s_pcqq_aiomsg 挂起命令 echo mem > /sys ...
- Fiddler抓包8-打断点(bpu)
前言 先给大家讲一则小故事,在我们很小的时候是没有手机的,那时候跟女神聊天都靠小纸条.某屌丝A男对隔壁小王的隔壁女神C倾慕已久,于是天天小纸条骚扰,无奈中间隔着一个小王,这样小王就负责传小纸条了.有一 ...
- python 全栈开发,Day83(博客系统子评论,后台管理,富文本编辑器kindeditor,bs4模块)
一.子评论 必须点击回复,才是子评论!否则是根评论点击回复之后,定位到输入框,同时加入@评论者的用户名 定位输入框 focus focus:获取对象焦点触发事件 先做样式.点击回复之后,定位到输入框, ...
- Oracle中数值的计算
运算符 含义 · +(加) 加法 · ||(加) 字符串相加 · -(减) 减法 · *(乘) 乘法 · /(除) 除法 · mod(模)返回一个除法的整数余数 例如,12 % 5 ...
- Maven的下载,安装,配置,测试,初识以及Maven私服
:Maven目录分析 bin:含有mvn运行的脚本 boot:含有plexus-classworlds类加载器框架 conf:含有settings.xml配置文件 lib:含有Maven运行时所需要的 ...