BZOJ2631tree——LCT
题目描述
一棵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-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
输出
样例输入
1 2
2 3
* 1 3 4
/ 1 1
样例输出
提示
数据规模和约定
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
LCT,splay每个点维护子树和,单点权值和两个区间修改标记,注意加法和乘法运算顺序即可。开unsigned int即可,开longlong可能会T。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll unsigned int
using namespace std;
int n,m;
int x,y,z,w;
int mod=51061;
char ch[2];
int f[100010];
int s[100010][2];
int st[100010];
int r[100010];
int size[100010];
ll sum[100010];
ll val[100010];
ll a[100010];
ll b[100010];
int get(int rt)
{
return rt==s[f[rt]][1];
}
void change(int rt,int x,int y)
{
if(!rt)
{
return ;
}
sum[rt]=(sum[rt]*x+y*size[rt])%mod;
val[rt]=(val[rt]*x+y)%mod;
a[rt]=(a[rt]*x+y)%mod;
b[rt]=(b[rt]*x)%mod;
}
void pushup(int rt)
{
sum[rt]=(sum[s[rt][0]]+sum[s[rt][1]]+val[rt])%mod;
size[rt]=(size[s[rt][0]]+size[s[rt][1]]+1)%mod;
}
void pushdown(int rt)
{
if(r[rt])
{
swap(s[rt][0],s[rt][1]);
r[s[rt][0]]^=1;
r[s[rt][1]]^=1;
r[rt]^=1;
}
int x=a[rt];
int y=b[rt];
a[rt]=0;
b[rt]=1;
if(x!=0||y!=1)
{
change(s[rt][0],y,x);
change(s[rt][1],y,x);
}
}
int is_root(int rt)
{
return s[f[rt]][0]!=rt&&s[f[rt]][1]!=rt;
}
void rotate(int rt)
{
int fa=f[rt];
int anc=f[fa];
int k=get(rt);
if(!is_root(fa))
{
s[anc][fa==s[anc][1]]=rt;
}
s[fa][k]=s[rt][k^1];
f[s[fa][k]]=fa;
s[rt][k^1]=fa;
f[fa]=rt;
f[rt]=anc;
pushup(fa);
pushup(rt);
}
void splay(int rt)
{
int top=0;
st[++top]=rt;
for(int i=rt;!is_root(i);i=f[i])
{
st[++top]=f[i];
}
for(int i=top;i>=1;i--)
{
pushdown(st[i]);
}
for(int fa;!is_root(rt);rotate(rt))
{
if(!is_root(fa=f[rt]))
{
rotate(get(rt)==get(fa)?fa:rt);
}
}
}
void access(int rt)
{
for(int x=0;rt;x=rt,rt=f[rt])
{
splay(rt);
s[rt][1]=x;
pushup(rt);
}
}
void reverse(int rt)
{
access(rt);
splay(rt);
r[rt]^=1;
}
void split(int x,int y)
{
reverse(x);
access(y);
splay(y);
}
void link(int x,int y)
{
reverse(x);
f[x]=y;
}
void cut(int x,int y)
{
reverse(x);
access(y);
splay(y);
s[y][0]=f[x]=0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
size[i]=val[i]=sum[i]=b[i]=1;
}
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
link(x,y);
}
while(m--)
{
scanf("%s",ch);
scanf("%d%d",&x,&y);
if(ch[0]=='+')
{
scanf("%d",&z);
split(x,y);
change(y,1,z);
}
else if(ch[0]=='-')
{
scanf("%d%d",&w,&z);
cut(x,y);
link(w,z);
}
else if(ch[0]=='*')
{
scanf("%d",&z);
split(x,y);
change(y,z,0);
}
else if(ch[0]=='/')
{
split(x,y);
printf("%d\n",sum[y]);
}
}
}
BZOJ2631tree——LCT的更多相关文章
- Link-Cut Tree(LCT)&TopTree讲解
前言: Link-Cut Tree简称LCT是解决动态树问题的一种数据结构,可以说是我见过功能最强大的一种树上数据结构了.在此与大家分享一下LCT的学习笔记.提示:前置知识点需要树链剖分和splay. ...
- 一堆LCT板子
搞了一上午LCT,真是累死了-- 以前总觉得LCT高大上不好学不好打,今天打了几遍感觉还可以嘛= =反正现在的水平应付不太难的LCT题也够用了,就这样好了,接下来专心搞网络流. 话说以前一直YY不出来 ...
- 动态树之LCT(link-cut tree)讲解
动态树是一类要求维护森林的连通性的题的总称,这类问题要求维护某个点到根的某些数据,支持树的切分,合并,以及对子树的某些操作.其中解决这一问题的某些简化版(不包括对子树的操作)的基础数据结构就是LCT( ...
- 在此为LCT开一个永久的坑
其实我连splay都还不怎么会. 今天先抄了黄学长的bzoj2049,以后一定要把它理解了. 写LCT怎么能不%数据结构大神yeweining呢?%%%chrysanthemums %%%切掉大森林 ...
- 【BZOJ2157】旅游 LCT
模板T,SB的DMoon..其实样例也是中国好样例...一开始不会复制,yangyang:找到“sample input”按住shift,按page down.... #include <ios ...
- 【BZOJ3669】[Noi2014]魔法森林 LCT
终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...
- 【BZOJ1180】: [CROATIAN2009]OTOCI & 2843: 极地旅行社 LCT
竟然卡了我....忘记在push_down先下传父亲的信息了....还有splay里for():卡了我10min,但是双倍经验还是挺爽的,什么都不用改. 感觉做的全是模板题,太水啦,不能这么水了... ...
- 【BZOJ3282】Tree LCT
1A爽,感觉又对指针重怀信心了呢= =,模板题,注意单点修改时splay就好,其实按吾本意是没写的也A了,不过应该加上能更好维护平衡性. ..还是得加上好= = #include <iostre ...
- BZOJ2888 资源运输(LCT启发式合并)
这道题目太神啦! 我们考虑他的每一次合并操作,为了维护两棵树合并后树的重心,我们只好一个一个的把节点加进去.那么这样一来看上去似乎就是一次操作O(nlogn),但是我们拥有数据结构的合并利器--启发式 ...
随机推荐
- 【Atcoder yahoo-procon2019-qual D】 Ears
Atcoder yahoo-procon2019-qual D 题意:给你\(L\)个耳朵(???),以及一条范围从\(0\)到\(L\)的数轴,你可以选择一个出发点,从该点开始随意走动,如果经过了\ ...
- 完整卸载 kUbuntu-desktop from Ubuntu 14.04 LTS系统 ubuntu14.04 LTS 64Bit
sudo apt-get remove libkde3support4 k3b-data ntrack-module-libnl-0 libkrosscore4 libgpgme++2 libqapt ...
- Selenium:利用select模块处理下拉框
在利用selenium进行UI自动化测试过程中,经常会遇到下拉框选项,这篇博客,就介绍下如何利用selenium的Select模块来对标准select下拉框进行操作... 首先导入Select模块: ...
- 如何下载google play商店里面的app?
如何不FQ的下载这国际版的app呢? 方法如下: https://androidappsapk.co/category/apps/ 你可以直接登入这个网站,下载你所需要的国际版的软件. 就像是踏入一个 ...
- Luogu3162 CQOI2012 组装 贪心
传送门 如果提供每一种零件的生产车间固定了,那么总时间\(t\)与组装车间的位置\(x\)的关系就是 \(t = \sum (x-a_i)^2 = nx^2-2\sum a_ix + \sum a_i ...
- Vue-Vue组件的注册和使用
全局注册: 要注册一个全局组件,可以使用 Vue.component(tagName, options). 注意确保在初始化根实例之前注册组件: html代码: <div id="ex ...
- eclipse 打包
add directory entries 不勾选, spring 自动扫描之类的扫描不到
- C# LINQ 详解 From Where Select Group Into OrderBy Let Join
目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. ...
- 在python中使用正则表达式(一)
在python中通过内置的re库来使用正则表达式,它提供了所有正则表达式的功能. 一.写在前面:关于转义的问题 正则表达式中用“\”表示转义,而python中也用“\”表示转义,当遇到特殊字符需要转义 ...
- React 等框架使用 index 做 key 的问题
React 等框架使用 index 做 key 的问题 假如有两个树,一个是之前,一个是更变之后,我们抽象成两种可能性. 插入内容在最后 插入内容在最前 关于插在中间,原理一样,就不阐述. 使用 ul ...