题目大意:给你一棵树,让你维护一个数据结构,支持

边的断,连

树链上所有点点权加上某个值

树链上所有点点权乘上某个值

求树链所有点点权和

(辣鸡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)的更多相关文章

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

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

  2. BZOJ 2631 tree | Luogu P1501 [国家集训队]Tree II (LCT 多重标记下放)

    链接:https://www.luogu.org/problemnew/show/P1501 题面: 题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: ...

  3. 洛谷.1501.[国家集训队]Tree II(LCT)

    题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...

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

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

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

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

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

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

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

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

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

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

  9. 洛谷 1501 [国家集训队]Tree II BZOJ 2631 Tree

    [题解] 维护乘法标记和加法标记的LCT #include<cstdio> #include<algorithm> #define Mod (51061) #define N ...

随机推荐

  1. 找不到javax.servlet.http.HttpServletResponse和javax.servlet.http.HttpServletRequest

    导了个项目进eclipse,发现很多文件都报了错,错误提示是没有引入javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServl ...

  2. 【ACM-ICPC 2018 南京赛区网络预赛 L】Magical Girl Haze

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 定义dis[i][j]表示到达i这个点. 用掉了j次去除边的机会的最短路. dis[1][0]= 0; 在写松弛条件的时候. 如果用 ...

  3. MYSQL数据的安装、配置

    linux安装mysql服务分两种安装方法: 1.源码安装,优点是安装包比较小,只有十多M,缺点是安装依赖的库多,安装编译时间长,安装步骤复杂容易出错. 2.使用官方编译好的二进制文件安装,优点是安装 ...

  4. C#--文件操作的一些技巧

    Using的特点 Using 打开什么,就自动关闭什么,using中包含的其他类是否关闭,using是不管的 XML文档读取 重点:必须是标准的xml文档,否则会出错 string xmlxx = @ ...

  5. BA-siemens-BA模块特性

    PXC24(包含UEC24的模块特性) DO点可以接220vac的电压,渠道人员告知电流不要超过2A AO点只能输出0-10V的电压,不能输出4-20ma的电流,说明书上是错误的 AO点输出10v失败 ...

  6. Android漫游记(6)---APP启动之旅(I)

    Android基于Linux2.6+内核,我们看一张图,以对Android系统的架构有个感性的认识. 我们从Kernel层简单说明: 1.Kernel层:基于Linux2.6+内核.同一时候做了一些嵌 ...

  7. NHibernate之旅(14):探索NHibernate中使用视图

    本节内容 引入 1.持久化类 2.映射文件 3.測试 结语 引入 在数据库操作中,我们除了对表操作,还有视图.存储过程等操作,这一篇和下篇来学习这些内容.这篇我们来学习怎样在NHibernate中使用 ...

  8. iOS库--.a与.framework

    一.什么是库? 库是共享程序代码的方式,一般分为静态库和动态库. 二.静态库与动态库的差别? 静态库:链接时完整地拷贝至可运行文件里.被多次使用就有多份冗余拷贝. 动态库:链接时不复制.程序执行时由系 ...

  9. 多线程的join和interrupt

    你可以在一个线程1里添加线程2对象thread的join方法来让线程1处于等待的状态 ,同时也可以调用thread.interrupt()来打断等待状态,此处注意 interrupt应在线程1开启st ...

  10. Oracle 中UNDO与REDO的差别具体解释

    一 为了更清楚的看出2者差别,请看下表:                                               UNDO                             ...