洛谷 P1501 [国家集训队]Tree II Link-Cut-Tree
Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std; void setIO(string a)
{
freopen((a+".in").c_str(),"r",stdin);
freopen((a+".out").c_str(),"w",stdout);
} #define maxn 100009
#define ll long long
#define mod 51061 int f[maxn], ch[maxn][2],siz[maxn],tag[maxn],sta[maxn],n,m;
ll mult[maxn], add[maxn], sumv[maxn], val[maxn]; int lson(int x)
{
return ch[x][0];
}
int rson(int x)
{
return ch[x][1];
}
int get(int x)
{
return ch[f[x]][1]==x;
}
int isRoot(int x)
{
return !(ch[f[x]][1]==x||ch[f[x]][0]==x);
}
void mark(int x)
{
if(!x)return;
swap(ch[x][0], ch[x][1]), tag[x]^=1;
} void pushdown(int x){
// if(!x)return;
if(mult[x]!=1)
{
if(lson(x))
{
sumv[lson(x)]*=mult[x];
mult[lson(x)]*=mult[x];
add[lson(x)]*=mult[x];
val[lson(x)]*=mult[x]; add[lson(x)]%=mod;
mult[lson(x)]%=mod;
sumv[lson(x)]%=mod;
val[lson(x)]%=mod;
}
if(rson(x))
{
sumv[rson(x)]*=mult[x];
mult[rson(x)]*=mult[x];
add[rson(x)]*=mult[x];
val[rson(x)]*=mult[x]; add[rson(x)]%=mod;
mult[rson(x)]%=mod;
sumv[rson(x)]%=mod;
val[rson(x)]%=mod;
}
mult[x]=1;
}
if(add[x])
{
if(lson(x))
{
sumv[lson(x)]+=add[x]*siz[lson(x)];
add[lson(x)]+=add[x];
val[lson(x)]+=add[x]; add[lson(x)]%=mod;
sumv[lson(x)]%=mod;
val[lson(x)]%=mod;
}
if(rson(x))
{
sumv[rson(x)]+=add[x]*siz[rson(x)];
add[rson(x)]+=add[x];
val[rson(x)]+=add[x]; add[rson(x)]%=mod;
sumv[rson(x)]%=mod;
val[rson(x)]%=mod;
}
add[x]=0;
}
if(tag[x]) mark(ch[x][0]), mark(ch[x][1]), tag[x]=0;
} void pushup(int x)
{
if(!x)return;
siz[x]=siz[lson(x)]+siz[rson(x)]+1;
sumv[x]=(sumv[lson(x)]+sumv[rson(x)]+val[x])%mod;
} void rotate(int o){
int old=f[o],fold=f[old],which=get(o);
if(!isRoot(old)) ch[fold][ch[fold][1]==old]=o;
f[o]=fold;
ch[old][which]=ch[o][which^1], f[ch[old][which]]=old;
ch[o][which^1]=old,f[old]=o;
pushup(old),pushup(o),pushup(fold);
}
void splay(int x){
int v=0,u=x;
sta[++v]=u;
while(!isRoot(u)) sta[++v]=f[u],u=f[u];
while(v) pushdown(sta[v--]);
u=f[u];
for(int fa;(fa=f[x])!=u;rotate(x))
if(f[fa]!=u) rotate(get(x)==get(fa)?fa:x);
}
void Access(int x)
{
for(int y=0;x;y=x,x=f[x]) splay(x), ch[x][1]=y, pushup(x);
}
void makeRoot(int x)
{
Access(x), splay(x),mark(x);
}
void split(int x,int y)
{
makeRoot(x), Access(y), splay(y);
}
void Link(int x,int y)
{
makeRoot(x), f[x]=y;
}
void cut(int x,int y)
{
makeRoot(x), Access(y), splay(y);
f[x] = ch[y][0] = 0, pushup(y);
} void debug(){ for(int i=1;i<=n;++i) printf("%d %lld\n",siz[i],sumv[i]); } int main(){
//setIO("input");
memset(add,0,sizeof(add)), memset(mult,1,sizeof(mult));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) sumv[i]=val[i]=1;
for(int i=1;i<n;++i)
{
int a,b;
scanf("%d%d",&a,&b);
Link(a,b);
} for(int i=1;i<=m;++i)
{
char opt[10];
int a,b,c,d;
scanf("%s",opt);
if(opt[0]=='+')
{
scanf("%d%d%d",&a,&b,&c);
split(a,b);
sumv[b]+=siz[b]*c;
add[b]+=c;
val[b]+=c; sumv[b]%=mod;
add[b]%=mod;
val[b]%=mod;
}
if(opt[0]=='-')
{
scanf("%d%d%d%d",&a,&b,&c,&d);
cut(a,b);
Link(c,d);
}
if(opt[0]=='*')
{
scanf("%d%d%d",&a,&b,&c);
split(a,b);
sumv[b]*=c;
add[b]*=c;
mult[b]*=c;
val[b]*=c; sumv[b]%=mod;
add[b]%=mod;
mult[b]%=mod;
val[b]%=mod;
}
if(opt[0]=='/')
{
scanf("%d%d",&a,&b);
split(a,b);
printf("%lld\n",sumv[b]%mod);
}
}
return 0;
}
洛谷 P1501 [国家集训队]Tree II Link-Cut-Tree的更多相关文章
- 洛谷 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
题目描述 一棵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)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- [洛谷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
看来这个LCT板子并没有什么问题 #include<cstdio> #include<algorithm> using namespace std; typedef long ...
- [洛谷P1501] [国家集训队]Tree II(LCT模板)
传送门 这是一道LCT的板子题,说白了就是在LCT上支持线段树2的操作. 所以我只是来存一个板子,并不会讲什么(再说我也不会,只能误人子弟2333). 不过代码里的注释可以参考一下. Code #in ...
- 【洛谷 P3690】 【模板】Link Cut Tree (动态树)
题目链接 \(RT\). FlashHu巨佬的博客 #include <cstdio> #define R register int #define I inline void #defi ...
随机推荐
- ANSI编码
ANSI编码 ANSI简介 不同的国家和地区制定了不同的标准,由此产生了 GB2312.GBK.Big5.Shift_JIS 等各自的编码标准.这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸 ...
- swoole-简单的异步执行
swoole-简单的异步执行 标签(空格分隔): php 理解 一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作. 阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞 ...
- RBAC介绍
基于角色的权限访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关联,用户通过成为适当角色的成 ...
- STL数组和com数组相互转换的做法
作者:朱金灿 来源:http://blog.csdn.net/clever101 STL的泛型数组是vetor,com的泛型数组类型是VARIANT.二者怎样能相互转化呢?就是说怎么把一个vector ...
- Android 实现下拉刷新和上拉加载更多的RECYCLERVIEW和SCROLLVIEW
PullRefreshRecyclerView.java /** * 类说明:下拉刷新上拉加载更多的RecyclerView * Author: gaobaiq * Date: 2016/5/9 18 ...
- (转载)10个实用的但偏执的Java编程技术
10个实用的但偏执的Java编程技术 在沉浸于编码一段时间以后(比如说我已经投入近20年左右的时间在程序上了),你会渐渐对这些东西习以为常.因为,你知道的…… 作者:小峰来源:码农网|2015-09- ...
- 静态构造函数c# 静态块java initallize oc
静态构造函数c# 静态块java initallize oc 先看一道常见题目,以下代码的执行结果是什么? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 ...
- .NET 拼音汉字转化(全面)
引言 这是一个.NET 用C#语言编写的 拼音转汉字类,考虑到有很多拼音转汉字,但是试用过发现大部分有很多生僻字都没有办法显示.在此分享一个支持绝大多数的较为全面的拼音汉字转化帮助类.不多说,代码附 ...
- 利用js自带函数 数组去重
<script> ,,]; //原数组 var a=[]; //定义空数组 arr.map(function(x){ //用 map 遍历数组 ){ //如果当前值没有存在空数组中 a.p ...
- du -sh*查看当前目录下的文件夹大小
du -sh*查看当前目录下的文件夹大小 u 命令 用途 概述磁盘使用. 语法 du [ -a | -s ] [ -k ] [ -m ] [ -g ][ -l ] [ -r ] ...