BZOJ 2631 [国家集训队]Tree II (LCT)
题目大意:给你一棵树,让你维护一个数据结构,支持
边的断,连
树链上所有点点权加上某个值
树链上所有点点权乘上某个值
求树链所有点点权和
(辣鸡bzoj又是土豪题,洛谷P1501传送门)
LCT裸题,下传标记,搞法类似于洛谷线段树模板2
先下传乘法标记,val,sum,乘法标记,加法标记都要乘
再下传加法标记,val,加法标记直接加,sum应该加上子树size*加的值
卡了10分钟我发现打标记应该同时更新这个位置的实际值
又卡了10分钟发现我下传完标记忘记清零了
然而我又忘记了一个事情被卡了20分钟!乘法标记能下传的条件是,乘法标记不等于1 而不是 不等于0!!!
智商已下线
#include <cstdio>
#include <algorithm>
#include <cstring>
#define il inline
#define ui unsigned int
#define mod 51061
#define N 101000
using namespace std; int n,m,tp;
int stk[N];
struct LinkCutTree{
int fa[N],ch[N][],rv[N];
ui sz[N],sum[N],val[N],add[N],mul[N];
il int idf(int x){return ch[fa[x]][]==x?:;}
il void con(int x,int ff,int p){fa[x]=ff,ch[ff][p]=x;}
il int isroot(int x){return (ch[fa[x]][]!=x&&ch[fa[x]][]!=x)?:;}
il void rev(int x){swap(ch[x][],ch[x][]),rv[x]^=;}
il void pushup(int x)
{
sum[x]=(sum[ch[x][]]+sum[ch[x][]]+val[x])%mod;
sz[x]=sz[ch[x][]]+sz[ch[x][]]+;
}
il void pushdown(int x)
{
#define ls ch[x][0]
#define rs ch[x][1]
if(mul[x]!=)
{
sum[ls]=(sum[ls]*mul[x])%mod,sum[rs]=(sum[rs]*mul[x])%mod;
val[ls]=(val[ls]*mul[x])%mod,val[rs]=(val[rs]*mul[x])%mod;
mul[ls]=(mul[ls]*mul[x])%mod,mul[rs]=(mul[rs]*mul[x])%mod;
add[ls]=(add[ls]*mul[x])%mod,add[rs]=(add[rs]*mul[x])%mod;
mul[x]=;
}
if(add[x])
{
sum[ls]=(sum[ls]+(sz[ls]%mod*add[x])%mod)%mod;
sum[rs]=(sum[rs]+(sz[rs]%mod*add[x])%mod)%mod;
val[ls]=(val[ls]+add[x])%mod;
val[rs]=(val[rs]+add[x])%mod;
add[ls]=(add[ls]+add[x])%mod;
add[rs]=(add[rs]+add[x])%mod;
add[x]=;
}
if(rv[x])
{
if(ch[x][]) rev(ch[x][]);
if(ch[x][]) rev(ch[x][]);
rv[x]=;
}
#undef ls
#undef rs
}
il void rot(int x)
{
int y=fa[x];int ff=fa[y];int px=idf(x);int py=idf(y);
if(!isroot(y)) ch[ff][py]=x;
fa[x]=ff;con(ch[x][px^],y,px),con(y,x,px^);
pushup(y),pushup(x);
}
void splay(int x)
{
int y=x;stk[++tp]=x;
while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];}
while(tp){pushdown(stk[tp--]);}
while(!isroot(x))
{
y=fa[x];
if(isroot(y)) rot(x);
else if(idf(y)==idf(x)) rot(y),rot(x);
else rot(x),rot(x);
}
}
void access(int x){for(int y=;x;y=x,x=fa[x])splay(x),ch[x][]=y,pushup(x);}
//int findrt(int x){access(x),splay(x);while(ch[x][0])pushdown(x),x=ch[x][0];return x;}
il void mkroot(int x){access(x),splay(x),rev(x);}
il void split(int x,int y){mkroot(x),access(y),splay(y);}
il void link(int x,int y){mkroot(x),access(y),splay(y),fa[x]=y;}
il void cut(int x,int y){split(x,y);fa[x]=ch[y][]=,pushup(y);}
}lct;
int gint()
{
int rett=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){rett=(rett<<)+(rett<<)+c-'';c=getchar();}
return rett*fh;
} int main()
{
n=gint(),m=gint();
int x,y;ui z;char str[];
for(int i=;i<=n;i++)
lct.sz[i]=lct.val[i]=lct.sum[i]=lct.mul[i]=;
for(int i=;i<n;i++)
x=gint(),y=gint(),lct.link(x,y);
for(int i=;i<=m;i++)
{
scanf("%s",str);
if(str[]=='+'){
x=gint(),y=gint(),z=gint();
lct.split(x,y);
lct.sum[y]=(lct.sum[y]+(lct.sz[y]*z)%mod)%mod;
lct.val[y]=(lct.val[y]+z)%mod;
lct.add[y]=(lct.add[y]+z)%mod;
}else if(str[]=='-'){
x=gint(),y=gint(),lct.cut(x,y);
x=gint(),y=gint(),lct.link(x,y);
}else if(str[]=='*'){
x=gint(),y=gint(),z=gint();
lct.split(x,y);
lct.sum[y]=(lct.sum[y]*z)%mod;
lct.val[y]=(lct.val[y]*z)%mod;
lct.mul[y]=(lct.mul[y]*z)%mod;
lct.add[y]=(lct.add[y]*z)%mod;
}else if(str[]=='/'){
x=gint(),y=gint(),lct.split(x,y);
printf("%u\n",lct.sum[y]);
}
}
return ;
}
BZOJ 2631 [国家集训队]Tree II (LCT)的更多相关文章
- BZOJ 2631 tree / Luogu P1501 [国家集训队]Tree II (LCT,多重标记)
题意 一棵树,有删边加边,有一条链加/乘一个数,有询问一条链的和 分析 LCT,像线段树一样维护两个标记(再加上翻转标记就是三个),维护size,就行了 CODE #include<bits/s ...
- BZOJ 2631 tree | Luogu P1501 [国家集训队]Tree II (LCT 多重标记下放)
链接:https://www.luogu.org/problemnew/show/P1501 题面: 题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: ...
- 洛谷.1501.[国家集训队]Tree II(LCT)
题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...
- 洛谷P1501 [国家集训队]Tree II(LCT)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- LUOGU P1501 [国家集训队]Tree II (lct)
传送门 解题思路 \(lct\),比较模板的一道题,路径加和乘的维护标记与线段树\(2\)差不多,然后剩下就没啥了.但调了我将近一下午.. 代码 #include<iostream> #i ...
- P1501 [国家集训队]Tree II LCT
链接 luogu 思路 简单题 代码 #include <bits/stdc++.h> #define ls c[x][0] #define rs c[x][1] using namesp ...
- P1501 [国家集训队]Tree II(LCT)
P1501 [国家集训队]Tree II 看着维护吧2333333 操作和维护区间加.乘线段树挺像的 进行修改操作时不要忘记吧每个点的点权$v[i]$也处理掉 还有就是$51061^2=2607225 ...
- 洛谷 P1501 [国家集训队]Tree II 解题报告
P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...
- 洛谷 1501 [国家集训队]Tree II BZOJ 2631 Tree
[题解] 维护乘法标记和加法标记的LCT #include<cstdio> #include<algorithm> #define Mod (51061) #define N ...
随机推荐
- OPENGL学习【一】VS2008开发OPENGL程序开发环境搭建
1.VS2008工具自行在网上下载安装,现只提供VS2008开发工具中配置OPENGL环境的详细步骤.开发包及编译工具会在下方一并放出链接. 2.打开CMake的工具,主要的配置信息如下,按照数字顺序 ...
- Project Euler 14 Longest Collatz sequence
题意:对于任意一个数 N ,寻找在 100,0000 之内按照规则( N 为奇数 N = N * 3 + 1 ,N 为偶数 N = N / 2 ,直到 N = 1 时的步数 )步数的最大值 思路:记忆 ...
- [GSS5] Can you answer these queries V
大力讨论. luogu上交spoj的题卡的一比... 难受 wa了好几次,原因大概首先求的是非空区间,不能乱和0取max,第二点是求无相交的解时,在两段求lmx和rmx的时候可以取max(0). 区间 ...
- [LeetCode] 347. 前K个高频元素
python 版方法1:链表 class Solution(object): def topKFrequent(self, nums, k): """ :type num ...
- 《黑白团团队》第八次团队作业:Alpha冲刺 第三天
项目 内容 作业课程地址 任课教师首页链接 作业要求 团队项目 填写团队名称 黑白团团队 填写具体目标 认真负责,完成项目 团队项目Github仓库地址链接. 第三天 日期:2019/6/17 成员 ...
- linux网络监控脚本
http://www.51testing.com/html/92/77492-828434.html
- H3C SecPath U200-S 如何在内网使用外网IP地址访问内网服务器
H3C SecPath U200-S 如何在内网使用外网IP地址访问内网服务器 ------------------------------------------------------------ ...
- VMware虚拟机无法识别U盘解决方式
1. 本机情况: Winxp操作系统(相同应该适用于win7),VMware虚拟机.虚拟机版本号:VMware 10.安装Ubuntu14.04.现要求在主机上插入U盘.在虚拟机中显示. 2. 遇到问 ...
- win7-32虚拟机安装
前置条件:安装好VMware-workstation 一.本人本机win7—32位 准备win7_32位镜像文件GSP1RMCULFRER_CN_DVD.iso 新建一个文件夹,将它保存在我们的新建文 ...
- BZOJ 4027: [HEOI2015]兔子与樱花 贪心
4027: [HEOI2015]兔子与樱花 Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号 ...