BZOJ2631: tree(LCT)
Description
一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。
Input
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
Sample Input
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
4
解题思路:
假如没有2操作,且图是树,是不是想起了线段树。
这道题也是一样的道理,LCT嘛,splay维护树链
代码:
// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll tr[spc].ch[0]
#define rrr tr[spc].ch[1]
#define ls ch[0]
#define rs ch[1]
typedef unsigned int lnt;
const lnt mod=;
struct trnt{
int ch[];
int fa;
int lzt;
lnt add;
lnt mul;
lnt sum;
lnt wgt;
lnt val;
bool anc;
}tr[];
int st[];
int tp;
int n,q;
char cmd[];
int read()
{
int f=,x=;
char ss=getchar();
while(ss<''||ss>''){if(ss=='-')f=-;ss=getchar();}
while(ss>=''&&ss<=''){x=x*+ss-'';ss=getchar();}
return f*x;
}
int comd(void)
{
if(cmd[]=='+')
return ;
if(cmd[]=='-')
return ;
if(cmd[]=='*')
return ;
if(cmd[]=='/')
return ;
return ;
}
bool whc(int spc)
{
return tr[tr[spc].fa].rs==spc;
}
void pushup(int spc)
{
tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+;
tr[spc].sum=(tr[lll].sum+tr[rrr].sum+tr[spc].val)%mod;
}
void trr(int spc)
{
if(!spc)
return ;
tr[spc].lzt^=;
std::swap(lll,rrr);
}
void Mul(int spc,lnt k)
{
if(!spc)
return ;
tr[spc].add=tr[spc].add*k%mod;
tr[spc].sum=tr[spc].sum*k%mod;
tr[spc].val=tr[spc].val*k%mod;
tr[spc].mul=tr[spc].mul*k%mod;
}
void Add(int spc,lnt k)
{
if(!spc)
return ;
if(tr[spc].mul)
{
Mul(lll,tr[spc].mul);
Mul(rrr,tr[spc].mul);
tr[spc].mul=;
}
tr[spc].sum=(tr[spc].sum+tr[spc].wgt*k)%mod;
tr[spc].val=(tr[spc].val+k)%mod;
tr[spc].add=(tr[spc].add+k)%mod;
}
void pushdown(int spc)
{
if(tr[spc].lzt)
{
tr[spc].lzt=;
trr(lll);
trr(rrr);
}
if(tr[spc].mul!=)
{
Mul(lll,tr[spc].mul);
Mul(rrr,tr[spc].mul);
tr[spc].mul=;
}
if(tr[spc].add)
{
Add(lll,tr[spc].add);
Add(rrr,tr[spc].add);
tr[spc].add=;
}
}
void rotate(int spc)
{
int f=tr[spc].fa;
bool k=whc(spc);
tr[f].ch[k]=tr[spc].ch[!k];
tr[spc].ch[!k]=f;
if(tr[f].anc)
{
tr[spc].anc=;
tr[f].anc=;
}else
tr[tr[f].fa].ch[whc(f)]=spc;
tr[spc].fa=tr[f].fa;
tr[f].fa=spc;
tr[tr[f].ch[k]].fa=f;
pushup(f);
pushup(spc);
}
void splay(int spc)
{
tp=;
int x=spc;
while(!tr[x].anc)
st[++tp]=x,x=tr[x].fa;
st[++tp]=x;
while(tp)
pushdown(st[tp--]);
while(!tr[spc].anc)
{
int ft=tr[spc].fa;
if(tr[ft].anc)
{
rotate(spc);
return ;
}
if(whc(spc)^whc(ft))
rotate(spc);
else
rotate(ft);
rotate(spc);
}
pushup(spc);
}
void access(int spc)
{
int lst=;
while(spc)
{
splay(spc);
tr[rrr].anc=;
tr[lst].anc=;
rrr=lst;
pushup(spc);
lst=spc;
spc=tr[spc].fa;
}
}
void Mtr(int spc)
{
access(spc);
splay(spc);
trr(spc);
}
void split(int x,int y)
{
Mtr(x);
access(y);
splay(y);
}
void link(int x,int y)
{
Mtr(x);
tr[x].fa=y;
}
void cut(int x,int y)
{
split(x,y);
tr[y].ls=;
tr[x].fa=;
tr[x].anc=;
pushup(y);
}
int main()
{
n=read();
q=read();
for(int i=;i<=n;i++)
{
tr[i].anc=;
tr[i].mul=;
tr[i].val=;
tr[i].wgt=tr[i].sum=;
}
for(int i=;i<n;i++)
{
int a=read(),b=read();
link(a,b);
}
while(q--)
{
scanf("%s",cmd);
int opt=comd();
if(opt==)
{
int u=read(),v=read(),c=read();
split(u,v);
Add(v,c);
}
if(opt==)
{
int ua=read(),va=read(),ub=read(),vb=read();
cut(ua,va);
link(ub,vb);
}
if(opt==)
{
int u=read(),v=read(),c=read();
split(u,v);
Mul(v,c);
}
if(opt==)
{
int u=read(),v=read();
split(u,v);
printf("%u\n",tr[v].sum);
}
}
return ;
}
BZOJ2631: tree(LCT)的更多相关文章
- 【BZOJ】3282: Tree(lct)
http://www.lydsy.com/JudgeOnline/problem.php?id=3282 复习了下lct,发现两个问题.. 1:一开始我以为splay那里直接全部rot(x)就好了,然 ...
- 3282: Tree(LCT)
3282: Tree Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 2249 Solved: 1042[Submit][Status][Discus ...
- Link-Cut Tree(LCT) 教程
目录 前置知识 介绍 Access FindRoot MakeRoot Split Link Cut 关于Splay中操作的一点说明: 模板 前置知识 请先对树链剖分和Splay有所了解.LCT基于树 ...
- 洛谷P3690 【模板】Link Cut Tree (LCT)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- LUOGU P3690 【模板】Link Cut Tree (lct)
传送门 解题思路 \(lct\)就是基于实链剖分,用\(splay\)来维护每一条实链,\(lct\)的维护对象是一棵森林.\(lct\)支持很多神奇的操作: \(1.\) \(access\):这是 ...
- LuoguP3690 【模板】Link Cut Tree (LCT)
勉强算是结了个大坑吧或者才开始 #include <cstdio> #include <iostream> #include <cstring> #include ...
- 从ZOJ2114(Transportation Network)到Link-cut-tree(LCT)
[热烈庆祝ZOJ回归] [首先声明:LCT≠动态树,前者是一种数据结构,而后者是一类问题,即:LCT—解决—>动态树] Link-cut-tree(下文统称LCT)是一种强大的数据结构,不仅可以 ...
- Device Tree(三):代码分析【转】
转自:http://www.wowotech.net/linux_kenrel/dt-code-analysis.html Device Tree(三):代码分析 作者:linuxer 发布于:201 ...
- 「ZJOI2018」历史(LCT)
「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...
随机推荐
- Task Scheduler
https://technet.microsoft.com/en-us/library/cc748993(v=ws.11).aspx#BKMK_winui If Task Scheduler is n ...
- zzulioj--1089--make pair(dfs+模拟)
1809: make pair Time Limit: 1 Sec Memory Limit: 128 MB Submit: 60 Solved: 44 SubmitStatusWeb Board ...
- centos7 双网卡设置(先NAT和后桥接)
摘要:VMware中搭建一台虚拟机192.168.161.5(NAT转发) 首先在VM虚拟机设置里面添加一块网卡适配器 设置为桥接模式 完成后等待自动配置 此时出现多了一个ens37 和本地网段一样的 ...
- dubbo+zookeeper+springMVC +maven
pom: <dependency> <groupId>com.github.sgroschupf</grou ...
- 转:Java读写文件各种方法及性能比较
干Java这么久,一直在做WEB相关的项目,一些基础类差不多都已经忘记.经常想得捡起,但总是因为一些原因,不能如愿. 其实不是没有时间,只是有些时候疲于总结,今得空,下定决心将丢掉的都给捡起来. 文件 ...
- Java经典算法案例
笔试中的编程题3 JAVA经典算法40例[程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? ...
- 如何更改AD域安全策略-密码必须符合复杂性要求
通常我们在域系统-管理工具上面是找不到“域安全策略”的,我们只能找到“本地安全策略”,而更改“本地安全策略”是不会对域产生任何的作用的.下面这个步骤教你如何找到“域安全策略” 1.Start(开始)– ...
- 简单学习Python之路1
如何在cmd中打开文件:先用win+R打开cmd界面,在已知到你自己要打开文件的地址之后比如(F:\workspace),你先按F:,然后在用cd workspace进入workspace的文件中,然 ...
- 初尝Perl -- 使用aapt给apk软件包批量重命名
不知道什么是Perl猛戳这个链接 http://zh.wikipedia.org/wiki/Perl 任务: 随着手机/平板的各方面性能的不断发展(CPU,内存 ...
- 具体解释window.location
window.location 对象所包括的属性 hash//从井号 (#) 開始的 URL(锚) host//主机名和当前 URL 的port号 hostname//当前 URL 的主机名 href ...