BZOJ2759 一个动态树好题 LCT
题解:
的确是动态树好题
首先由于每个点只有一个出边
这个图构成了基环内向树
我们观察那个同余方程组
一旦形成环的话我们就能知道环上点以及能连向环上点的值是多少了
所以我们只需要用一种结构来维护两个不是直接相连点的状态
由于有删边连边操作,比较容易想到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的更多相关文章
- BZOJ2759一个动态树好题 LCT
题如其名啊 昨天晚上写了一发忘保存 只好今天又码一遍了 将题目中怕$p[i]$看做$i$的$father$ 可以发现每个联通块都是一个基环树 我们对每个基环删掉环上一条边 就可以得到一个森林了 可以用 ...
- 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? 动态树是一类要求维护森林的连通性的题的总称 ...
随机推荐
- laravel windows安装
第一步安装composer 下载地址:https://getcomposer.org/ 第二步:更改laravel下载地址 选项一.全局配置(推荐) $ composer config -g repo ...
- Daily Codeforces 计划 训练时录
时间 场次 过题数目 补题数目 难易度 2019.4.7 codeforces-1141 ...
- Python菜鸟快乐游戏编程_pygame(6)
Python菜鸟快乐游戏编程_pygame(博主录制,2K分辨率,超高清) https://study.163.com/course/courseMain.htm?courseId=100618802 ...
- 桥接模式-Bridge(Java实现)
桥接模式-Bridge 桥梁模式的用意是"将抽象化(Abstraction)与实现化(Implementation)脱耦, 将"类的功能层次结构" 与 "类的实 ...
- sed命令(二)
转自:https://www.cnblogs.com/maxincai/p/5146338.html sed命令用法 sed是一种流编辑器,它是文本处理中非常有用的工具,能够完美的配合正则表达式使用, ...
- 如何参与flink开源项目
参与flink开源项目 https://flink.apache.org/how-to-contribute.html 1.回答社区问题 2.撰写bug报告 3.对于改进建议或新的特征 4.帮助别人并 ...
- 移动端返回上一页,刚需!document.referrer 详解
返回上一页,在PC端我们可以使用:history.go(-1)或者history.back(),可以正常返回第一层.这样,我们不需要上一页的 url 具体是什么,只要使用 history 一般都没啥问 ...
- 20164305 徐广皓 Exp2 后门原理与实践
实验内容 (1)使用netcat获取主机操作Shell,cron启动 (2)使用socat获取主机操作Shell, 任务计划启动 (3)使用MSF meterpreter(或其他软件)生成可执行文件, ...
- postgresql设置主键
replace(((uuid_generate_v4())::character varying)::text, '-'::text, ''::text)
- 开发一个项目之ES2015+
变量的解构赋值 任何部署了 Iterator 的对象都可 for of 循环(数组.Set.Map.某些类似数组的对象(arguments对象.DOM NodeList 对象).Generator 对 ...