链接:https://www.luogu.org/problemnew/show/P1501

题面:

题目描述

一棵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<=10^5,0<=c<=10^4

By (伍一鸣)

思路:

写法跟线段树差不多,修改i下pushdown多维护连个标记就好了。

实现代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ls c[x][0]
#define rs c[x][1]
const int M = 4e5+;
const int inf = 1e9;
const int mod = ;
int top;
int sum[M],c[M][],val[M],fa[M],rev[M],mn[M],S[M],tmp[M];
int siz[M],mul[M],add[M];
inline void up(int x){
//cout<<sum[x]<<" "<<sum[ls]<<" "<<sum[rs]<<" "<<val[x]<<endl;
sum[x] = (sum[ls] + sum[rs] + val[x])%mod;
siz[x] = (siz[ls] + siz[rs] + )%mod;;
} inline void pushrev(int x){
swap(ls,rs); rev[x] ^= ;
} inline void pushmul(int x,int c){
mul[x] = (1LL*mul[x]*c)%mod;
add[x] = (1LL*add[x]*c)%mod;
sum[x] = (1LL*sum[x]*c)%mod;
val[x] = (1LL*val[x]*c)%mod;
//cout<<mul[x]<<" "<<val[x]<<endl;
} inline void pushadd(int x,int c){
add[x] = (add[x] + c)%mod;
val[x] = (val[x] + c)%mod;
sum[x] = (1LL*sum[x]+1LL*siz[x]*c)%mod;
} inline bool isroot(int x){
return c[fa[x]][]!=x&&c[fa[x]][]!=x;
} inline void rotate(int x){
int y = fa[x],z = fa[y];
int k = c[y][] == x;
if(!isroot(y)) c[z][c[z][]==y]=x;
fa[x] = z;
c[y][k] = c[x][k^]; fa[c[x][k^]] = y;
c[x][k^] = y; fa[y] = x;
up(y); up(x);
} inline void pushdown(int x){
if(rev[x]){
if(ls) pushrev(ls);
if(rs) pushrev(rs);
rev[x] = ;
}
if(mul[x]!=){
if(ls) pushmul(ls,mul[x]);
if(rs) pushmul(rs,mul[x]);
mul[x] = ;
}
if(add[x]){
if(ls) pushadd(ls,add[x]);
if(rs) pushadd(rs,add[x]);
add[x] = ;
}
} inline void splay(int x){
S[top=]=x;
for(int i = x;!isroot(i);i=fa[i]) S[++top] = fa[i];
while(top) pushdown(S[top--]);
while(!isroot(x)){
int y = fa[x],z = fa[y];
if(!isroot(y))
(c[y][]==x)^(c[z][]==y)?rotate(x):rotate(y);
rotate(x);
}
} inline void access(int x){
for(int y = ;x;y = x,x = fa[x])
splay(x),c[x][] = y,up(x);
} inline void makeroot(int x){
access(x); splay(x); pushrev(x);
} inline void split(int x,int y){
makeroot(x); access(y); splay(y);
} inline void link(int x,int y){
makeroot(x);fa[x] = y;
} inline void cut(int x,int y){
split(x,y); fa[x] = c[y][] = ; up(y);
} inline int findroot(int x){
access(x); splay(x);
while(ls) x = ls;
return x;
} int main()
{
int n,q,u,v,x,y,k;
scanf("%d%d",&n,&q);
for(int i = ;i <= n;i ++) val[i] = mul[i] = ;
for(int i = ;i < n;i ++){
scanf("%d%d",&u,&v);
link(u,v);
}
char op[];
while(q--){
scanf("%s",op);
scanf("%d%d",&u,&v);
if(op[] == '+') {
scanf("%d",&k);
split(u,v); pushadd(v,k);
}
else if(op[] == '-'){
scanf("%d%d",&x,&y);
cut(u,v); link(x,y);
}
else if(op[] == '*'){
scanf("%d",&k);
split(u,v); pushmul(v,k);
}
else if(op[] == '/'){
//cout<<u<<" "<<v<<endl;
split(u,v); printf("%d\n",sum[v]);
}
}
return ;
}

BZOJ 2631 tree | Luogu P1501 [国家集训队]Tree II (LCT 多重标记下放)的更多相关文章

  1. BZOJ 2631 tree / Luogu P1501 [国家集训队]Tree II (LCT,多重标记)

    题意 一棵树,有删边加边,有一条链加/乘一个数,有询问一条链的和 分析 LCT,像线段树一样维护两个标记(再加上翻转标记就是三个),维护size,就行了 CODE #include<bits/s ...

  2. LUOGU P1501 [国家集训队]Tree II (lct)

    传送门 解题思路 \(lct\),比较模板的一道题,路径加和乘的维护标记与线段树\(2\)差不多,然后剩下就没啥了.但调了我将近一下午.. 代码 #include<iostream> #i ...

  3. P1501 [国家集训队]Tree II(LCT)

    P1501 [国家集训队]Tree II 看着维护吧2333333 操作和维护区间加.乘线段树挺像的 进行修改操作时不要忘记吧每个点的点权$v[i]$也处理掉 还有就是$51061^2=2607225 ...

  4. 洛谷 P1501 [国家集训队]Tree II 解题报告

    P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...

  5. P1501 [国家集训队]Tree II LCT

    链接 luogu 思路 简单题 代码 #include <bits/stdc++.h> #define ls c[x][0] #define rs c[x][1] using namesp ...

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

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  7. 【刷题】洛谷 P1501 [国家集训队]Tree II

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

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

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

  9. p1501 [国家集训队]Tree II

    传送门 分析 lct板子题 单独维护一下加和乘的情况即可 维护方法和维护翻转差不多 代码 #include<iostream> #include<cstdio> #includ ...

随机推荐

  1. MFC GDI绘图

    DC——MFC设备描述表类(也叫设备环境.设备上下文).默认起始点(0,0),带To的函数会移动起始点到指定位置. 新建单个文档的MFC应用程序,类视图——View项的属性——消息,WM_PAINT, ...

  2. SP4546 ANARC08A - Tobo or not Tobo IDA*

    题意:

  3. OpenSSL 通过OCSP手动验证证书

    翻译:https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html?utm_sour ...

  4. 南京IT公司

    公司 (排名不分前后,有好的公司可以@我,及时更新) 1.中兴软创 http://www.ztesoft.com/cn/index.html 2.华为 http://www.huawei.com/cn ...

  5. Transformer模型总结

    Transformer改进了RNN最被人诟病的训练慢的缺点,利用self-attention机制实现快速并行. 它是由编码组件.解码组件和它们之间的连接组成. 编码组件部分由一堆编码器(6个 enco ...

  6. 7.19T3

    小 X 的图 题目背景及题意 小 X 有一张图,有 n 个点(从 0 开始编号),一开始图里并没有 边,他有时候会向其中添加一条双向边(x 到 y).小 X 会时不时想知 道某两个点是否联通,如果连通 ...

  7. poj1737

    Connected Graph POJ - 1737 An undirected graph is a set V of vertices and a set of E∈{V*V} edges.An ...

  8. Python基础面试题整理

    基础 Python中lambda是什么意思 Python中的pass是什么意思 作为解释型语言,Python如何运行 什么是Python的单元测试 在Python中unittest是什么 如何将数字转 ...

  9. Flask-认识flask

    Python 现阶段三大主流Web框架 Django Tornado Flask 对比 百度百科 1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, ...

  10. OpsManage安装过程中遇到的问题和解决方案

    系统地址:https://github.com/welliamcao/OpsManage 系统:ubuntu ubuntu使用apt-get进行自动化安装 自带python2.7,不需要再次安装 1. ...