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,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作

Output

  对于每个/对应的答案输出一行

Sample Input

3 2
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)的更多相关文章

  1. 【BZOJ】3282: Tree(lct)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3282 复习了下lct,发现两个问题.. 1:一开始我以为splay那里直接全部rot(x)就好了,然 ...

  2. 3282: Tree(LCT)

    3282: Tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 2249  Solved: 1042[Submit][Status][Discus ...

  3. Link-Cut Tree(LCT) 教程

    目录 前置知识 介绍 Access FindRoot MakeRoot Split Link Cut 关于Splay中操作的一点说明: 模板 前置知识 请先对树链剖分和Splay有所了解.LCT基于树 ...

  4. 洛谷P3690 【模板】Link Cut Tree (LCT)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  5. LUOGU P3690 【模板】Link Cut Tree (lct)

    传送门 解题思路 \(lct\)就是基于实链剖分,用\(splay\)来维护每一条实链,\(lct\)的维护对象是一棵森林.\(lct\)支持很多神奇的操作: \(1.\) \(access\):这是 ...

  6. LuoguP3690 【模板】Link Cut Tree (LCT)

    勉强算是结了个大坑吧或者才开始 #include <cstdio> #include <iostream> #include <cstring> #include ...

  7. 从ZOJ2114(Transportation Network)到Link-cut-tree(LCT)

    [热烈庆祝ZOJ回归] [首先声明:LCT≠动态树,前者是一种数据结构,而后者是一类问题,即:LCT—解决—>动态树] Link-cut-tree(下文统称LCT)是一种强大的数据结构,不仅可以 ...

  8. Device Tree(三):代码分析【转】

    转自:http://www.wowotech.net/linux_kenrel/dt-code-analysis.html Device Tree(三):代码分析 作者:linuxer 发布于:201 ...

  9. 「ZJOI2018」历史(LCT)

    「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...

随机推荐

  1. linux下oracle11G DG搭建(三):环绕备库搭建操作

    linux下oracle11G DG搭建(三):环绕备库搭建操作 环境 名称 主库 备库 主机名 bjsrv shsrv 软件版本号 RedHat Enterprise5.5.Oracle 11g 1 ...

  2. CAShapeLayer的简单介绍以及基本使用

    1.CAShapeLayer简单介绍  1.1CAShapeLayer继承于CALayer,能够使用CALayer的全部属性值:    1.2CAShapeLayer须要贝塞尔曲线配合使用才有意义(也 ...

  3. 将本地的代码上传到网上SVN库

    使用VisualSVN Server创建版本库: https://jingyan.baidu.com/article/db55b609f6aa724ba20a2f6c.html 最详细的教程: htt ...

  4. javascript中 visibility和display的区别

    visibility属性用来确定元素是显示还是隐藏的,这用visibility="visible|hidden"来表示(visible表示显示,hidden表示隐藏). 当visi ...

  5. weex入门(一)

    emmmm其实没有接触过weex ,了解一番发现有很多坑,有很多基于weex改良后的框架,比如weexplus等等,基本不用踩多少坑.经过几天的深思熟虑我觉得还是去踩坑,毕竟踩完坑才能真正的了解嘛 w ...

  6. 原型,构造函数,实例,__proto__

    再说说__proto__,这个孩子性格慢向,所以即使在现代浏览器广为支持得今天也不建议使用,性能特别慢,而且影响所有来自该[[prototype]]的对象.只是拿出来了解了解: 1.它是个啥? 原型对 ...

  7. WPF通用框架ZFS《项目结构介绍01》_模块介绍

    首页介绍: 下图为项目运行首页图片, 大的结构分为三块: 1.Header首部模块(存放通知组件[全局通知.消息管理 ].扩展模块[皮肤.系统设置.关于作者.退出系统]) 2.Left左侧菜单模块(存 ...

  8. 父类与子类的virtual

    父类加了virtual,子类不需要加virtual,多余.加了也不会报错. 父类中不是virtual,子类是virtual,那么父类中的不是虚函数,子类及子子类的派生类中该函数才是虚函数

  9. 发送邮件被退回,提示: Helo command rejected: Invalid name 错误

    我自己配置的 postfix + dovecot server, 配置了outlook 后, 相同的账号. 在有的电脑上能收发成功, 在有的电脑上发送邮件就出现退信.提示 Helo command r ...

  10. [Python] String Join

    Let's introduce a new string method, join: >>> nautical_directions = "\n".join([& ...