tree bzoj-2631

题目大意:给定一个n个点的树,每个点的初始权值为1,支持:删边加边(这两个操作同时进行,保证操作之后还是一棵树),路径加,路径乘,查询路径和。

注释:$1\le n,q\le 10^5$,$1\le c \le 10^4$。

想法:暴力给的很优雅:15‘没有加边删边且保证是链,我们直接用线段树维护。50'没有加边删边,我们裸上树剖+线段树。满分的话我们用LCT维护加边删边。

具体地:我的习惯是先×后+,所以每一次乘法都先将加法标记也进行修改。询问的话直接makeroot,我们节点信息直接维护原树子树信息,然后对应的查询就是链上的信息。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100050
#define mod 51061
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
typedef unsigned int ui;
int n,m,ch[N][2],f[N],rev[N];
ui sum[N],mul[N],add[N],siz[N],val[N];
char opt[10];
inline bool isrt(int x)
{
return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
}
void pushdown(int p)
{
if(mul[p]!=1)
{
ui u=mul[p];
sum[ls]=sum[ls]*u%mod; mul[ls]=mul[ls]*u%mod; add[ls]=add[ls]*u%mod; val[ls]=val[ls]*u%mod;
sum[rs]=sum[rs]*u%mod; mul[rs]=mul[rs]*u%mod; add[rs]=add[rs]*u%mod; val[rs]=val[rs]*u%mod;
mul[p]=1;
}
if(add[p])
{
ui d=add[p];
sum[ls]=(sum[ls]+siz[ls]*d%mod)%mod; add[ls]=(add[ls]+d)%mod; val[ls]=(val[ls]+d)%mod;
sum[rs]=(sum[rs]+siz[rs]*d%mod)%mod; add[rs]=(add[rs]+d)%mod; val[rs]=(val[rs]+d)%mod;
add[p]=0;
}
if(rev[p])
{
swap(ch[ls][0],ch[ls][1]);
swap(ch[rs][0],ch[rs][1]);
rev[ls]^=1; rev[rs]^=1;
rev[p]=0;
}
}
void pushup(int p)
{
siz[p]=siz[ls]+siz[rs]+1;
sum[p]=(sum[ls]+sum[rs]+val[p])%mod;
}
void update(int p)
{
if(!isrt(p)) update(f[p]);
pushdown(p);
}
void rotate(int x)
{
int y=f[x],z=f[y],k=get(x);
if(!isrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
pushup(y); pushup(x);
}
void splay(int x)
{
update(x);
for(int fa;fa=f[x],!isrt(x);rotate(x))
if(!isrt(fa))
rotate(get(fa)==get(x)?fa:x);
}
void access(int p)
{
int t=0;
while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
}
void makeroot(int p)
{
access(p); splay(p); swap(ls,rs); rev[p]^=1;
}
void link(int x,int p)
{
makeroot(x); f[x]=p;
}
void cut(int x,int p)
{
makeroot(x); access(p); splay(p); ls=f[x]=0;
}
void split(int x,int p)
{
makeroot(x); access(p); splay(p);
}
int main()
{
scanf("%d%d",&n,&m);
int i,x,y,z,w;
for(i=1;i<=n;i++) val[i]=mul[i]=siz[i]=sum[i]=1;
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y); link(x,y);
}
for(i=1;i<=m;i++)
{
scanf("%s%d%d",opt,&x,&y);
int p=y;
if(opt[0]=='+')
{
scanf("%d",&z); split(x,p);
sum[p]=(sum[p]+siz[p]*z%mod)%mod;
val[p]=(val[p]+z)%mod;
add[p]=(add[p]+z)%mod;
}
else if(opt[0]=='-')
{
scanf("%d%d",&z,&w); cut(x,y); link(z,w);
}
else if(opt[0]=='*')
{
scanf("%d",&z); split(x,p);
sum[p]=sum[p]*z%mod;
val[p]=val[p]*z%mod;
add[p]=add[p]*z%mod;
mul[p]=mul[p]*z%mod;
}
else
{
split(x,p); printf("%u\n",sum[p]);
}
}
}

小结:LCT是个好东西。

[bzoj2631]tree_LCT的更多相关文章

  1. bzoj2631 3282

    这两题都是link cut tree的裸题之前看Qtree的论文,只会在确定父子关系的情况下连边和删边如果在任意两个点连边删边怎么做呢?这时候我们不能随意的将一个点的父节点设为另一个点,因为其中某个点 ...

  2. bzoj2631: tree

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  3. BZOJ2631——tree

    1.题目大意:bzoj1798的lct版本 2.分析:这个把线段树改成splay就好 #include <stack> #include <cstdio> #include & ...

  4. 【bzoj2631】tree link-cut-tree

    2016-06-01 08:50:36 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2631 注意加和乘的标记下传问题. 还有就是split后 ...

  5. bzoj2631: tree lct

    要打mul和add的lct 50000+的mod用unsigned int好了TAT (坑爹没打pc('\n');(静态)调了好久,样例竟然只输出一个,orz,也不提示PE T_T) #include ...

  6. LCT模板(BZOJ2631)

    用LCT实现路径加,路径乘,断开及加上一条边(保证是树),查询路径和. #include <cstdio> #include <algorithm> #define l(x) ...

  7. 【BZOJ2631】tree

    Description 一棵n个点的树.每一个点的初始权值为1. 对于这棵树有q个操作,每一个操作为下面四种操作之中的一个: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 ...

  8. bzoj2631

    题解: lct+链上修改 每一次修改的时候记录lazy标记 如果有了乘法,加法的lazy标记也要相应的随之变化 代码: #pragma GCC optimize(2) #include<bits ...

  9. 【bzoj2631】tree LCT

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一:+ u v c:将u到v的路径上的点的权值都加上自然数c:- u1 v1 u2 v2:将树中原有的边( ...

随机推荐

  1. C++ Web 编程(菜鸟教程)

    C++ Web 编程(菜鸟教程) C++ Web 编程 什么是 CGI? 公共网关接口(CGI),是一套标准,定义了信息是如何在 Web 服务器和客户端脚本之间进行交换的. CGI 规范目前是由 NC ...

  2. 清橙A1206.小Z的袜子 && CF 86D(莫队两题)

    清橙A1206.小Z的袜子 && CF 86D(莫队两题) 在网上看了一些别人写的关于莫队算法的介绍,我认为,莫队与其说是一种算法,不如说是一种思想,他通过先分块再排序来优化离线查询问 ...

  3. JS文件中的中文在网页上显示为乱码解决方法

    转自:http://www.pc6.com/infoview/Article_63835.html 如果JS文件中的中文在网页上显示为乱码,不妨采用本文章中的方法来试一试,或许能解决使你很头疼的问题. ...

  4. Oracle 12.2.0.1 RAC for rhel 7.X 数据库安装(节点1执行root.sh失败)

    说明: 最开始是用的rehat7.2安装12.2.0.1,后面安装GI节点一执行root.sh脚本失败,排查原因,最开始以为是操作系统的问题,换成rehat7.6,同样的出现问题,经过一番折腾,后面通 ...

  5. JavaScript 函数 伪数组 arguments

    一.函数 函数:函数就是将一些语言进行封装,然后通过调用的形式,执行这些语句. 函数的作用: 1.将大量重复的语句写在函数里,以后需要这些语句的时候,可以直接调用函数,避免重复劳动 2.简化编程,让变 ...

  6. ★Java语法(二)——————————数据类型及装换

    整数类型: 1.byte型:8位(1字节)  范围:-128~127 用法:byte x = 35 : 2.short型:16位(2字节)  范围:-32768~32767 用法:short x = ...

  7. 《Linux程序设计》笔记(二)shell程序设计

    1. 进程树形显示 ps -e f 2. 重定向 > 覆盖文件 >> 附加至文件 1> 标准输出 2> 标准错误输出 0 代表一个程序的标准输入 3. 程序可以在当前目录 ...

  8. hadoop单机环境配置

    1.配置一台linux服务器(当前使用CentOS7)及一些基本设置 1.1在wmware下制作一台centos服务器(桥接模式)         并设置静态ip (编辑/etc/sysmconfig ...

  9. java中负数的补码转换为十进制

    一个数如果为正,则它的原码.反码.补码相同:一个正数的补码,将其转化为十进制,可以直接转换. 已知一个负数的补码,将其转换为十进制数,步骤: 1.先对各位取反: 2.将其转换为十进制数: 3.加上负号 ...

  10. [Intermediate Algorithm] - Arguments Optional

    题目 创建一个计算两个参数之和的 function.如果只有一个参数,则返回一个 function,该 function 请求一个参数然后返回求和的结果. 例如,add(2, 3) 应该返回 5,而 ...