bzoj2631 tree LCT 区间修改,求和
tree
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 4962 Solved: 1697
[Submit][Status][Discuss]
Description
一棵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的余数。
Input
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
Sample Input
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
HINT
数据规模和约定
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
题解:
基本操作,可以作为模板题
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio> #define N 100007
#define ll unsigned int
using namespace std;
const int mod=;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,q;
ll sum[N],num[N],add[N],mul[N],rev[N],siz[N];
int c[N][],fa[N],st[N]; void change(int p,ll mu,ll ad)
{
if (!p) return;
mul[p]=mul[p]*mu%mod;
add[p]=(add[p]*mu+ad)%mod;
num[p]=(num[p]*mu+ad)%mod;
sum[p]=(sum[p]*mu+ad*siz[p])%mod;
}
void update(int p)
{
int l=c[p][],r=c[p][];
siz[p]=(siz[l]+siz[r]+)%mod;
sum[p]=(sum[l]+sum[r]+num[p])%mod;
}
void pushdown(int p)
{
int l=c[p][],r=c[p][];
if (rev[p])
{
rev[p]^=,rev[l]^=,rev[r]^=;
swap(c[p][],c[p][]);
}
if (add[p]!=||mul[p]!=)
{
change(l,mul[p],add[p]);
change(r,mul[p],add[p]);
}
add[p]=,mul[p]=;
}
inline bool isroot(int x)
{
return c[fa[x]][]!=x&&c[fa[x]][]!=x;
}
void rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if (c[y][]==x) l=;else l=;r=l^;
if (!isroot(y))
{
if (c[z][]==y) c[z][]=x;
else c[z][]=x;
}
fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
c[y][l]=c[x][r],c[x][r]=y;
update(y),update(x);
}
void splay(int x)
{
int top=;st[++top]=x;
for (int i=x;!isroot(i);i=fa[i])
st[++top]=fa[i];
for (int i=top;i>=;i--)
pushdown(st[i]);
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if (!isroot(y))
{
if (c[y][]==x^c[z][]==y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
int t=;
while(x)
{
splay(x);
c[x][]=t;
update(x);
t=x,x=fa[x];
}
}
void makeroot(int x)
{
access(x);
splay(x);
rev[x]^=;
}
void link(int x,int y)
{
makeroot(x);
fa[x]=y;
splay(x);
}
void cut(int x,int y)
{
makeroot(x);
access(y);
splay(y);
fa[x]=c[y][]=;
}
int main()
{
// freopen("fzy.in","r",stdin);
// freopen("fzy.out","w",stdout); n=read(),q=read();
for (int i=;i<=n;i++)num[i]=sum[i]=mul[i]=siz[i]=;
for (int i=;i<n;i++)
{
int u=read(),v=read();
link(u,v);
}
for (int i=;i<=q;i++)
{
char ch[];
scanf("%s",ch);
switch(ch[])
{
case'+':
{
int u=read(),v=read();ll c=read();
makeroot(u),access(v),splay(v);
change(v,,c);break;
}
case'-':
{
int u1=read(),v1=read(),u2=read(),v2=read();
cut(u1,v1),link(u2,v2);break;
}
case'*':
{
int u=read(),v=read();ll c=read();
makeroot(u),access(v),splay(v);
change(v,c,);break;
}
case'/':
{
int u=read(),v=read();
makeroot(u);
access(v);
splay(v);
printf("%d\n",sum[v]);
break;
}
}
}
}
bzoj2631 tree LCT 区间修改,求和的更多相关文章
- poj 3468:A Simple Problem with Integers(线段树,区间修改求和)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 58269 ...
- HDU 5002 Tree LCT 区间更新
Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action?c ...
- HDU1698Just a Hook(线段树 + 区间修改 + 求和)
题目链接 分析:1-N区间内初始都是1,然后q个询问,每个询问修改区间[a,b]的值为2或3或者1,统计最后整个区间的和 本来想刷刷手速,结果还是写了一个小时,第一个超时,因为输出的时候去每个区间查找 ...
- bzoj2631: tree lct
要打mul和add的lct 50000+的mod用unsigned int好了TAT (坑爹没打pc('\n');(静态)调了好久,样例竟然只输出一个,orz,也不提示PE T_T) #include ...
- [bzoj2631]tree——lct
Brief Description 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: u v c:将u到v的路径上的点的权值都加上自然数c: u1 v1 u2 ...
- bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
- 线段树:Segment Tree(单点修改/区间修改模板) C++
线段树是非常有效的数据结构,可以快速的维护单点修改,区域修改,查询最大值,最小值等功能. 同时,它也很重要.如果有一天比赛,你卡在了一道线段树模板题目上,这就真的尴尬了.不过,随着时代的进步,题目也越 ...
- POJ - 3468 线段树单点查询,单点修改区间查询,区间修改模板(求和)
题意: 给定一个数字n,表示这段区间的总长度.然后输入n个数,然后输入q,然后输入a,b,表示查询a,b,区间和,或者输入c 再输入三个数字a,b,c,更改a,b区间为c 思路: 线段树首先就是递归建 ...
随机推荐
- 第一个 swift 项目
今天 学习了 一丢丢 swift,特此记录一下 ! 原来创建的时候 ,只要把 语言 由以前的Object-C改为Swift,变创建好了自己的swift工程 第一个简单的swift demo 上代码 i ...
- [ SNOI 2013 ] Quare
Description 题目链接 求一张无向带权图的边双连通生成子图的最小代价. Solution 核心的思路是,一个点双连通分量肯定是一堆环的并. 考虑增量地构造这个边双连通图,每次把一个环并进去, ...
- Android单独继承View类来实现自定义控件
一个单独继承view类来实现自定义控件,在该方法中,需要重写ondraw方法来绘制自己所需要的控件,下面也以一个简单的例子来说明如何实现自定义控件.该方法可以实现所需要的所有的自定义控件. 属性文件中 ...
- Oracle Recycle Bin
开启回收站RECYCLEBIN=ON,默认开启 ALTER SYSTEM SET RECYCLEBIN=OFF SCOPE=SPFILE; 一.从回收站还原表 还原删除的表和从属对象. 如果多个回收站 ...
- Python3基础教程(十六)—— 迭代器、生成器、装饰器
在这个实验里我们学习迭代器.生成器.装饰器有关知识. 这几个概念是 Python 中不容易理解透彻的概念,务必把所有的实验代码都完整的输入并理解清楚其中每一行的意思. 迭代器 Python 迭代器(I ...
- Linux之常用Shell脚本总结
一.简介本文将总结一些常用的shell脚本,方便以后工作中使用. 二.shell脚本[a]定期备份mysql数据库,需结合cronb定时任务调度实现. #!/bin/bash#首先声明一些自定义变量 ...
- luogu P1008 三连击
题目背景 本题为提交答案题,您可以写程序或手算在本机上算出答案后,直接提交答案文本,也可提交答案生成程序. 题目描述 将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数构成1:2: ...
- [LUOGU] P3004 [USACO10DEC]宝箱Treasure Chest
第一眼:区间DP,可以瞎搞 f[i][j]=max(sum(i,j)-f[i+1][j],sum(i,j)-f[i][j-1]) 提出来就是f[i][j]=sum(i,j)-min(f[i+1][j] ...
- python实现快速排序、冒泡
快速排序:首先任意选取一个数据(通常选用数组的第一个参数)作为关键数据,然后将比它小的数放在它前面,比它大的数放在后面,这个过程称之为快速排序 def quick_sort(l): if len(l) ...
- Apache web服务
1.apache 1> 世界上使用率最高的网站服务器,最高时可达70%:官方网站:apache.org 2> http 超文本协议 HTML超文本标记语言 3> URL 统一资源定位 ...