这个题是一个经典的维护路径信息的题,对于路径上的修改,我们只需要把对应的链\(split\)上来,然后修改最上面的点就好,注意pushdown的时候的顺序是先乘后加

然后下传乘法标记的时候,记得把对应的\(add\)标记也要乘,因为就跟线段树的下传标记类似

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define int long long using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 1e5+1e2;
const int mod = 51061; int ch[maxn][3];
int n,m;
int sum[maxn],val[maxn];
int che[maxn],add[maxn];
int fa[maxn],size[maxn];
int st[maxn];
int rev[maxn]; int son(int x)
{
if (ch[fa[x]][0]==x) return 0;
else return 1;
} bool notroot(int x)
{
return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
} void update(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;
} void reverse(int x)
{
swap(ch[x][0],ch[x][1]);
rev[x]^=1;
} void jia(int x,int d)
{
sum[x]+=size[x]*d;
sum[x]%=mod;
val[x]+=d;
val[x]%=mod;
add[x]+=d;
add[x]%=mod;
} void cheng(int x,int d)
{
sum[x]*=d;
sum[x]%=mod;
val[x]*=d;
val[x]%=mod;
add[x]*=d;
add[x]%=mod;
che[x]*=d;
che[x]%=mod;
}
void pushdown(int x)
{
if (che[x]!=1)
{
if (ch[x][0]) cheng(ch[x][0],che[x]);
if (ch[x][1]) cheng(ch[x][1],che[x]);
che[x]=1;
}
if (add[x])
{
if (ch[x][0]) jia(ch[x][0],add[x]);
if (ch[x][1]) jia(ch[x][1],add[x]);
add[x]=0;
}
if (rev[x])
{
if (ch[x][0]) reverse(ch[x][0]);
if (ch[x][1]) reverse(ch[x][1]);
rev[x]=0;
}
} void rotate(int x)
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y)) ch[z][c]=x;
fa[x]=z;
ch[y][b]=ch[x][!b];
fa[ch[x][!b]]=y;
ch[x][!b]=y;
fa[y]=x;
update(y);
update(x);
} void splay(int x)
{
int y=x,cnt=0;
st[++cnt]=y;
while (notroot(y)) y=fa[y],st[++cnt]=y;
while (cnt) pushdown(st[cnt--]);
while (notroot(x))
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y))
{
if (b==c) rotate(y);
else rotate(x);
}
rotate(x);
}
update(x);
} void access(int x)
{
for (int y=0;x;y=x,x=fa[x])
{
splay(x);
ch[x][1]=y;
update(x);
}
} void makeroot(int x)
{
access(x);
splay(x);
reverse(x);
} int findroot(int x)
{
access(x);
splay(x);
while (ch[x][0])
{
pushdown(x);
x=ch[x][0];
}
return x;
} void split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
} void link(int x,int y)
{
makeroot(x);
if (findroot(y)!=x) fa[x]=y;
} void cut(int x,int y)
{
split(x,y);
if (ch[x][0] || ch[x][1] || fa[x]!=y || ch[y][son(x)^1]) return;
fa[x]=ch[y][0]=0;
} char s[10]; signed main()
{
n=read(),m=read();
for (int i=1;i<=n;i++) che[i]=1,add[i]=0,val[i]=1;
for (int i=1;i<n;i++)
{
int x=read(),y=read();
link(x,y);
}
//split(1,3);
//cout<<sum[3]<<endl;
for(int i=1;i<=m;i++)
{
scanf("%s",s+1);
if (s[1]=='+')
{
int x=read(),y=read(),z=read();
split(x,y);
val[y]+=z;
val[y]%=mod;
sum[y]+=size[y]*z;
sum[y]%=mod;
add[y]+=z;
add[y]%=mod;
}
else
if (s[1]=='-')
{
int x=read(),y=read(),xx=read(),yy=read();
cut(x,y);
link(xx,yy);
}
else
if (s[1]=='/')
{
int x=read(),y=read();
split(x,y);
printf("%lld\n",sum[y]%mod);
}
else
{
int x=read(),y=read(),z=read();
//cout<<z<<endl;
split(x,y);
sum[y]*=z;
sum[y]%=mod;
val[y]*=z;
val[y]%=mod;
add[y]*=z;
add[y]%=mod;
che[y]*=z;
che[y]%=mod;
}
} return 0;
}

洛谷1501 Tree II(LCT,路径修改,路经询问)的更多相关文章

  1. 洛谷P1501 Tree II

    LCT 还是LCT的板子,下放标记和那道线段树2一样,先放乘..之前用char忘记getchar,调了好久... 注意开long long!! #include <bits/stdc++.h&g ...

  2. 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)

    点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...

  3. 点分治模板(洛谷P4178 Tree)(树分治,树的重心,容斥原理)

    推荐YCB的总结 推荐你谷ysn等巨佬的详细题解 大致流程-- dfs求出当前树的重心 对当前树内经过重心的路径统计答案(一条路径由两条由重心到其它点的子路径合并而成) 容斥减去不合法情况(两条子路径 ...

  4. 洛谷 P2764 LibreOJ 6002 最小路径覆盖问题

    题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开 ...

  5. BZOJ 2631 [国家集训队]Tree II (LCT)

    题目大意:给你一棵树,让你维护一个数据结构,支持 边的断,连 树链上所有点点权加上某个值 树链上所有点点权乘上某个值 求树链所有点点权和 (辣鸡bzoj又是土豪题,洛谷P1501传送门) LCT裸题, ...

  6. Poj1741/洛谷P4718 Tree(点分治)

    题面 有多组数据:Poj 无多组数据:洛谷 题解 点分治板子题,\(calc\)的时候搞一个\(two\ pointers\)扫一下统计答案就行了. #include <cmath> #i ...

  7. 洛谷P1198 [JSOI2008]最大数(单点修改,区间查询)

    洛谷P1198 [JSOI2008]最大数 简单的线段树单点问题. 问题:读入A和Q时,按照读入一个字符会MLE,换成读入字符串就可以了. #include<bits/stdc++.h> ...

  8. 洛谷.1501.[国家集训队]Tree II(LCT)

    题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...

  9. 洛谷P1501 [国家集训队]Tree II(LCT)

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

随机推荐

  1. spring之自定义注解

    java.lang.annotation提供了四种元注解,专门注解其他的注解: @Target –注解用于什么地方,默认值为任何元素,表示该注解用于什么地方.可用的ElementType指定参数 ,也 ...

  2. configparser生成模块写

    # -*-coding:utf-8-*-__author__ = "logan.xu"#写配置文件import configparserconfig = configparser. ...

  3. Python3-sqlalchemy-orm 分组统计

    #-*-coding:utf-8-*- #__author__ = "logan.xu" import sqlalchemy from sqlalchemy import crea ...

  4. python--接口自动化经常用到的pytest框架

    pytest常用的方法和原理 1.pytest的原理 pytest插件基于pluggy模块:pluggy有三个重要概念:HookspecMarker(用来定义hook函数),HookimplMarke ...

  5. APT组织跟踪与溯源

    前言 在攻防演练中,高质量的蓝队报告往往需要溯源到攻击团队.国内黑产犯罪团伙.国外APT攻击. 红队现阶段对自己的信息保护的往往较好,根据以往溯源成功案例来看还是通过前端js获取用户ID信息.mysq ...

  6. Python - 面向对象编程 - 小实战(3)

    需求 房子(House)有户型.总面积.家具名称列表:新房子没有任何的家具 家具(HouseItem)有名字.占地面积 席梦思(bed) 占地 4 平米 衣柜(bed) 占地 2 平米 餐桌(bed) ...

  7. Typora画各类流程图、甘特图、饼图等详细文档

    Draw Diagrams With Markdown August 15, 2016 by typora.io Typora supports some Markdown extensions fo ...

  8. tar 命令简介

    tar命令可以为linux的文件和目录创建档案.利用tar,可以为某一特定文件创建档案(备份文件),也可以在档案中改变文件,或者向档案中加入新的文件.tar最初被用来在磁带上创建档案,现在,用户可以在 ...

  9. vue2.0 前端框架

    在正式开始先复习一下js基础.因为vue最通终也要操作这些元素,vue和以前学的js并不挂勾,他和传统的jquert  设计理念相反 ## js 数据类型 1 基本类型 number  string  ...

  10. Windows难民安装docker的注意事项

    Windows下如何安装docker,这个没啥可说的,一直下一步就ok Windows  docker 下载地址: https://download.docker.com/win/stable/Doc ...