【刷题】洛谷 P1501 [国家集训队]Tree II
题目描述
一棵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的余数。
输入输出格式
输入格式:
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
输出格式:
对于每个/对应的答案输出一行
输入输出样例
输入样例#1:
3 2
1 2
2 3
* 1 3 4
/ 1 1
输出样例#1:
4
说明
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5*10^4,没有-操作
100%的数据保证,1<=n,q<=105,0<=c<=104
By (伍一鸣)
题解
这个题类似模板,只是变成了维护加法和乘法
类似于维护线段数时的加法和乘法
维护乘法时,要乘维护的和,点的权值和加法的lazy标记
维护加法的话,就直接加就行了
(这道题我有个地方少打了个=号,结果找了一个半小时。。)
#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
const int MAXN=100000+10,Mod=51061;
ll n,q,Val[MAXN];
struct LCT{
ll ch[MAXN][2],fa[MAXN],rev[MAXN],size[MAXN],sum[MAXN],add[MAXN],mul[MAXN];
inline void init()
{
for(register int i=1;i<=n;++i)Val[i]=size[i]=sum[i]=mul[i]=1;
memset(ch,0,sizeof(ch));
memset(fa,0,sizeof(fa));
memset(rev,0,sizeof(rev));
}
inline bool nroot(ll x)
{
return rc(fa[x])==x||lc(fa[x])==x;
}
inline void reverse(ll x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void plus(ll x,ll k)
{
(Val[x]+=k)%=Mod;
(sum[x]+=size[x]*k%Mod)%Mod;
(add[x]+=k)%=Mod;
}
inline void multi(ll x,ll k)
{
(Val[x]*=k)%=Mod;
(sum[x]*=k)%=Mod;
(add[x]*=k)%=Mod;(mul[x]*=k)%=Mod;
}
inline void pushup(ll x)
{
size[x]=size[lc(x)]+size[rc(x)]+1;
sum[x]=(sum[lc(x)]+sum[rc(x)]+Val[x])%Mod;
}
inline void pushdown(ll x)
{
if(mul[x]!=1)
{
multi(lc(x),mul[x]);multi(rc(x),mul[x]);
mul[x]=1;
}
if(add[x])
{
plus(lc(x),add[x]);plus(rc(x),add[x]);
add[x]=0;
}
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(ll x)
{
ll f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(ll x)
{
std::stack<ll> s;
s.push(x);
for(register int i=x;nroot(i);i=fa[i])s.push(fa[i]);
while(!s.empty())pushdown(s.top()),s.pop();
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(ll x)
{
for(register ll y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
}
inline void makeroot(ll x)
{
access(x);splay(x);reverse(x);
}
inline void split(ll x,ll y)
{
makeroot(x);access(y);splay(y);
}
inline void link(ll x,ll y)
{
makeroot(x);fa[x]=y;
}
inline void cut(ll x,ll y)
{
split(x,y);fa[x]=lc(y)=0;pushup(y);
}
};
LCT T;
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
read(n);read(q);
T.init();
for(register int i=1;i<n;++i)
{
ll u,v;
read(u);read(v);
T.link(u,v);
}
while(q--)
{
char opt;
std::cin>>opt;
if(opt=='+')
{
ll u,v,c;
read(u);read(v);read(c);
T.split(u,v);T.plus(v,c);
}
if(opt=='*')
{
ll u,v,c;
read(u);read(v);read(c);
T.split(u,v);T.multi(v,c);
}
if(opt=='/')
{
ll u,v;
read(u);read(v);
T.split(u,v);
write(T.sum[v],'\n');
}
if(opt=='-')
{
ll u1,v1,u2,v2;
read(u1);read(v1);read(u2);read(v2);
T.cut(u1,v1);T.link(u2,v2);
}
}
return 0;
}
【刷题】洛谷 P1501 [国家集训队]Tree II的更多相关文章
- 洛谷 P1501 [国家集训队]Tree II 解题报告
P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...
- 洛谷P1501 [国家集训队]Tree II(LCT,Splay)
洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...
- 洛谷P1501 [国家集训队]Tree II(LCT)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- 洛谷P1501 [国家集训队]Tree II(打标记lct)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- 洛谷 P1501 [国家集训队]Tree II
看来这个LCT板子并没有什么问题 #include<cstdio> #include<algorithm> using namespace std; typedef long ...
- [洛谷P1501] [国家集训队]Tree II(LCT模板)
传送门 这是一道LCT的板子题,说白了就是在LCT上支持线段树2的操作. 所以我只是来存一个板子,并不会讲什么(再说我也不会,只能误人子弟2333). 不过代码里的注释可以参考一下. Code #in ...
- [洛谷P1501][国家集训队]Tree II
题目大意:给一棵树,有四种操作: $+\;u\;v\;c:$将路径$u->v$区间加$c$ $-\;u_1\;v_1\;u_2\;v_2:$将边$u_1-v_1$切断,改成边$u_2-v_2$, ...
- 洛谷 P1501 [国家集训队]Tree II Link-Cut-Tree
Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...
- 洛谷.1501.[国家集训队]Tree II(LCT)
题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...
随机推荐
- 结对测试 vs 随机测试
在接口测试过程中,最关键的是对参数的各种情况进行测试. 随机测试是指随机选择一些参数值来测. 结对测试是指parewise算法生成较高“性价比”的组合情况来测. 随机测试存在的问题 随机,这两个字本身 ...
- SQL常见面试题
1.用一条SQL 语句 查询出每门课都大于80 分的学生姓名 name kecheng fenshu张三 语文 81张三 数学 75李四 语文 ...
- Linux命令应用大词典-第1章 登录、退出、关机和重启
1.1 login:用户登录系统 1.2 logout:退出登录shell 1.3 nologin:限制用户登录 1.4 exit:退出shell 1.5 sulogin:单用户登录(single u ...
- 在Maven上Web项目添加Spring框架
1. pom.xml添加Spring依赖包 <!-- spring 核心依赖--> <!-- context依赖beans,aop,core,expression;core依赖log ...
- python基础网络编程--转
python之网络编程 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的 ...
- 随手记录-linux-Linux目录结构
转:别人的 装完Linux,首先需要弄清Linux 标准目录结构 / root —?启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home —?存储普通用户的个人文件 ft ...
- crontab任务不生效
新建php脚本ctTest.php,代码如下: <?php /****************************************************************** ...
- 软工实践-Beta 冲刺 (4/7)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 1.界面的修改与完善 展示GitHub当日代码/文档签入记 ...
- 《TCP/IP 详解 卷1:协议》第 8 章:Internet 控制报文协议
路由器是 Internet 的重要组成部分,严密监视 Internet 的操作.IP 协议未给发送失败的 IP 数据包提供一种错误处理,也没有给端系统提供直接的方法来发现错误.为了解决这一不足之处,I ...
- BETA-5
前言 我们居然又冲刺了·五 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 过去两天完成了哪些任务 前一份代码方案全部垮掉,我,重构啦 接下来的计划 加速加速,一定要完成速度模块 ...