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. openstack 性能优化极致

  2. 最新昆石VOS2009/VOS3000手机号段导入文件(手机归属地)

    使用2017年4月最新版手机号段归属地制作,支持所有版本的VOS 共360569条记录,兼容所有版本的昆石VOS,包括VOS2009.vos3000.vos5000 导入比较简单.下载后解压到桌面在V ...

  3. [Apple开发者帐户帮助]一、开始(3)账户信息

    您帐户中显示的部分取决于您是否拥有免费帐户或是否已注册付费程序(Apple Developer Program或Apple Developer Enterprise Program).此外,您可以在这 ...

  4. go之数组

    一.数组概念 go语言提供了数组类型的数据结构 数组是具有 [唯一类型] 的一组 [固定长度] 的数据项序列,这种类型可以是任意类型 二.数组声明 var variable_name [SIZE]va ...

  5. Integer应该用==还是equals

    问题引出:“Integer应该用==还是equals” 讨论这个问题之前我们先放一段代码 public static void main(String[] args) { Integer a1 = 2 ...

  6. npm搭建React项目

    转自:http://blog.csdn.net/u012859720/article/details/70597119 要想使用npm,首先安装Node.js 一.安装全局包 $ npm instal ...

  7. JAVA 中进行网络通信时,通信的程序两端要传输的对象,不仅要序列化,而且这个对象所属的类的名字要完全一样,连包的名字都得一样

    如上图项目目录,这是一个简易的QQ,客户端登录的时候要传输用户信息到服务器验证,所以两端都会用到User类的对象,但一开始我在Server端的包名是com.qq.server.common,两端的报名 ...

  8. POJ 1985 求树的直径 两边搜OR DP

    Cow Marathon Description After hearing about the epidemic of obesity in the USA, Farmer John wants h ...

  9. 理解java中的ThreadLocal 专题

    ThreadLocal每一印象: public class IncrementWithStaticVariable{ private static int seqNum = 0; public int ...

  10. bootstrap的栅格系统和响应式工具

    关于bootstrap的响应式布局,昨天看了杨老师的视频教学https://www.bilibili.com/video/av18357039豁然开朗,在这里记录一下 一:meta标签的引用 < ...