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:\) 挺好想的.发现切换次数 ...
随机推荐
- 美团实习生电面之谈(成功拿到offer)
3月底进行了美团的一次实习生面试(Java研发project师).当时顺利的通过一面.以下是我的一面: 1.CPU由哪些部分组成 2.线程和进程的差别 3.Java类载入机制 4.怎样实现一个字符串的 ...
- js正则学习分享
http://www.cnblogs.com/rubylouvre/archive/2010/03/09/1681222.html http://www.cnblogs.com/tylerdonet/ ...
- 不允许 ASSIGNMENT 语句中包含 FOR XML 子句。
DECLARE @guidList NVARCHAR(max) SELECT @guidList=( CAST(OrderGUID AS nvarchar(max)) +',') FROM Order ...
- IPv4私有IP地址有哪些!
私有IP地址是一段保留的IP地址.只是使用在局域网中,在Internet上是不使用的. 私有IP地址的范围有: 私网地址分有三类, A类中,第一段为10的都为私网地址,B类中,以172.16--172 ...
- python3 类、对象的基础概念
类:具有相同特性和方法的抽象概念称为类 对象:从类中具体描述的一个事物称为对象 类和对象的关系:类是对象的抽象概念,对象是类的具体实例 class test001: #创建类 def __init__ ...
- PHP的数组分为两种类型,一种是索引数组,一种是关联数组。有如下关联数组,我们如何获取它的第一个key和value呢?
示例:$items=array('name'=>'sjm','age'=>'26','sex' => '男','location'=>'北京'); //当然用循环然后break ...
- vue踩坑-Error: listen EADDRNOTAVAIL 192.168.1.122:8081
每天上班,重启电脑,按照下面的步骤,打开vue的项目,开始编写代码,但是,今天一如往常一般操作:1:cd /项目名称 下面就是运行项目了,cd /项目名称,我的文件放在D盘,所以先进入d盘,再进入项目 ...
- 【Codeforces Round #424 (Div. 2) C】Jury Marks
[Link]:http://codeforces.com/contest/831/problem/C [Description] 有一个人参加一个比赛; 他一开始有一个初始分数x; 有k个评委要依次对 ...
- cogs 1396. wwww
1396. wwww ☆ 输入文件:wwww.in 输出文件:wwww.out 简单对比时间限制:1 s 内存限制:256 MB [题目描述] 对于一个递归函数w(a,b,c) 如果 ...
- 将Firefox设置为使用远程DNS
将Firefox设置为使用远程DNS 原文 https://www.my-proxy.com/blog/firefox-remote-dns 测试当前在用DNS https: ...