Luogu4332

LOJ2187

题解

代码-Tea

题意 : 每个点有三个儿子 , 给定叶节点的权值\(0\)或\(1\)且支持修改 , 非叶子节点的权值为当有\(>=2\)个儿子的权值为\(1\)的时候取\(1\) , 每次修改后求根节点输出
定义 : 权值可以取\(0,1,2,3\) ; 输出为\(0\)或\(1\)且权值\(>=2\)时输出为\(1\) .
限制 : 修改的都是叶子节点

考虑如果把输出\(0\)改成\(1\) , 则找到祖先中最深的权值不为\(1\)的点 , 这条链上的输出会改变 , 这里用\(LCT\)维护
如果把输出\(1\)改成\(0\) , 则找到祖先中最深的权值不为 \(2\) 的点 , 这条链上的输出会改变为\(0\)

这样有点麻烦 , 来一个转化 , 叶节点权值取值范围由\(0,1\)变为\(1,2\) ; 统一变成了权值\(2\)会对父亲产生贡献 , 权值\(1\)对父亲没有贡献

定义\(not1[x]=true\)的意义是\(x\)的子树中存在 权值不为\(1\)的点 , \(not2[]\)类似 .
只要写了\(pushdown\) , \(LCT\)也能区间打标记 .

打标记时先潦草地搞一下有类似\(not2[x]=not1[x],not1[x]=0\)的操作 , 之后在\(pushup\)的时候会有简单而正确的更新 : \(not1[x]=not1[ls]\ |\ not1[rs]\ |\ (val[x]!=1);\)
一定要想清楚所有状况才能说明这是对的 : 如果把\(0\)改成\(1\) , 可能碰到一个权值为\(0\)的点变成\(1\) , 或者\(2\)变成\(3\)而停止 ;
如果把\(1\)变成\(0\) , 可能碰到一个权值为\(1\)的点变成\(0\) , 或者\(3\)变成\(2\)而停止 .

所以\(pushup\)是\(LCT\)的关键 , 也是所有数据结构的关键 , 尽管在一般线段树题目中看不出来 ,
但在复杂一点的比如P4198楼房重建和 [HNOI/AHOI2018]转盘便显得非常重要了 .
类似地 , [NOIP2018]保卫王国中从下往上转移使得矩阵乘的更新顺序改变 , 说明\(pushup\)操作真的非常重要.
最简单的操作却能更新很难更新的情况,从而维护正确性

这道题还用到了一个点 , \(access\)可以使无关的点断开 , 而不直接\(fa[x]=0,ch[y][_]=0\)是因为\(access\)包括了\(pushup\)的更新
两个端点找出来以后就可以用上面说的修改和打标记了

注释更新于\(19.3.29\)

#include<bits/stdc++.h>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){register LL x=0,f=1;register char c=getchar();while(c<48||c>57){if(c=='-')f=-1;c=getchar();}while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();return f*x;
}const int MAXN=1.5e6+5;int fa[MAXN],to[MAXN][3];
int n,m;namespace LCT{int par[MAXN],ch[MAXN][2],val[MAXN],tag[MAXN];bool not1[MAXN],not2[MAXN];//定义not1[x]=true的意义是x的子树中存在权值不为1的点int st[MAXN],top;
#define ls (ch[rt][0])
#define rs (ch[rt][1])inline bool chk(int x){return ch[par[x]][1]==x;}inline bool isnotroot(int x){return ch[par[x]][0]==x||ch[par[x]][1]==x;}inline void pushup(int rt){not1[rt]=not1[ls]|not1[rs]|(val[rt]!=1);//最简单的维护却可以更新很难更新的情况,从而维护正确性.  pushup是LCT的关键not2[rt]=not2[ls]|not2[rs]|(val[rt]!=2);}inline void modify(int x,int y){val[x]+=y,tag[x]+=y;//区间树上打标记if(y>0) not2[x]=not1[x],not1[x]=0;//对整段val[]=1的区间加1,val[i]=0变1的误判会在pushup()里改正,然后就没有别的情况了else not1[x]=not2[x],not2[x]=0;//这里的修改只是简单的维护}inline void pushdown(int rt){if(!tag[rt]) return;if(ls) modify(ls,tag[rt]);if(rs) modify(rs,tag[rt]);tag[rt]=0;}inline void rotate(int x){int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];ch[y][k]=w,par[w]=y;if(isnotroot(y)) ch[z][chk(y)]=x; par[x]=z;ch[x][k^1]=y,par[y]=x;pushup(y);pushup(x);}inline void splay(int x){int y=x,top=0;while(1){st[++top]=y;if(isnotroot(y)) y=par[y];else break;}while(top) pushdown(st[top--]);while(isnotroot(x)){int y=par[x];if(isnotroot(y)){if(chk(x)==chk(y)) rotate(y);else rotate(x);}rotate(x);}}inline void access(int x){for(int y=0;x;x=par[y=x])splay(x),ch[x][1]=y,pushup(x);}inline int findnot1(int rt){pushdown(rt);if(!not1[rt]) return 0;if(not1[rs]) return findnot1(rs);//找到深度最大的不是1的点,即能够影响到的最远的点if(val[rt]!=1) return rt;return findnot1(ls);}inline int findnot2(int rt){pushdown(rt);if(!not2[rt]) return 0;if(not2[rs]) return findnot2(rs);if(val[rt]!=2) return rt;return findnot2(ls);}
#undef ls
#undef rs
}using namespace LCT;inline void dfs(int u){if(u>n) return;//因为初始数据一定是合法的,所以没必要往更深的地方走for(int i=0;i<=2;i++){int v=to[u][i];dfs(v);val[u]+=(val[v]>>1);//只有权值>=1的才有意义,先简单搞一下贡献}
//  val[u]>>=1;
}int main(){
//  freopen("asd.in","r",stdin);n=read();for(int i=1;i<=n;i++)for(int j=0;j<=2;j++){int x=read();to[i][j]=x;par[x]=i,fa[x]=i;}for(int i=n+1;i<=3*n+1;i++) val[i]=read()+1;//根据定义,val[u]应该+=(val[v]/2).(对于底层节点(其实适应于所有节点))考虑到转换的方便用1和2表示.//1就代表对上一层没贡献,2就代表有贡献.dfs(1);//算出初始的答案m=read();for(int i=1;i<=m;i++){int x=read();//实际上这里是一种卡常,如果split(x,y)就要makeroot极慢,所以改为这样access(x);splay(x);if(val[x]>1){int y=findnot2(ch[x][0]);
//          Debug(fa[y]); fa[y]是原树中的父亲,不是splay中的.access(fa[y]);//这里的作用是把无关的点断开,要access的理由是包括了pushup操作.splay(x);//access中使得根变了,所以要重新splay.modify(x,-1);}else{int y=findnot1(ch[x][0]);access(fa[y]);splay(x);modify(x,1);}splay(1);//要把1节点旋上来才能更新答案printf("%d\n",val[1]>>1);}
}

3.2原始注释

转载于:https://www.cnblogs.com/lizehon/p/10462097.html

P4332 [SHOI2014]三叉神经树(LCT)相关推荐

  1. [LCT刷题][树链信息维护] P4332 [SHOI2014]三叉神经树

    写在前面 把黑题看成蓝题结果想了老半天感觉不对劲 本题对于理解 S p l a y Splay Splay和 L C T LCT LCT结构具有至关重要的意义,值得反复思考. 可能因为我比较菜 题目思 ...

  2. SHOI2014 三叉神经树

    传送门 一道非常好的LCT/树剖题.但是像我这样的菜鸡想不到什么有效做法-- 首先我们可以很容易发现,一次如果要在链上连续修改那么肯定是从底向上的一端连续区间.如果我们把每个节点的输入值作为其权值,那 ...

  3. [SHOI2014]三叉神经树

    Description: 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的极大关注. SHOI 组织由若 ...

  4. 【LG-P4332 [SHOI2014]】三叉神经树 题解

    题面挺有意思(恶心)的. 传送门:P4332 [SHOI2014]三叉神经树 LCT Solution 1 对于每一个非叶子节点 iii,有 valival_ivali​,表示其输出为 1 的儿子的总 ...

  5. 三叉神经树 ( neuron )

    三叉神经树 ( neuron ) 题目描述 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物SHTSC 的密切联系引起了人们的极大关注. S ...

  6. LuoguP4383 [八省联考2018]林克卡特树lct

    LuoguP4383 [八省联考2018]林克卡特树lct https://www.luogu.org/problemnew/show/P4383 分析: 题意等价于选择\(K\)条点不相交的链,使得 ...

  7. luogu4383 bzoj5252[八省联考2018]林克卡特树lct

    ** [八省联考2018]林克卡特树lct** luogu bzoj 分析 很神仙的一道wqs二分.是真的不会切>-< 如果已经切完了,最优秀的方案就是每个联通块搞直径然后连起来一定是最优 ...

  8. P4332-[SHOI2014]三叉神经树【LCT】

    正题 题目链接:https://www.luogu.com.cn/problem/P4332 题目大意 给出nnn个点的一棵有根三叉树,保证每个点的儿子个数为333或者000,每个叶子有一个权值000 ...

  9. 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)

    题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...

最新文章

  1. java单点登录强制下线_实现单点登录并强制对方下线
  2. JS / 闭包的理解
  3. 建议15: 使用dynamic来简化反射实现
  4. P5712 【深基3.例4】Apples(python3实现)
  5. Windows Phone 实用开发技巧(18):使用SystemTray显示全局消息提醒
  6. 【Flink】Flink 源码阅读笔记(16)- Flink SQL 的元数据管理
  7. linux 目录权限上下文,文件和目录的安全上下文
  8. Hbase Cellutil源码
  9. 6.SpringMVC 配置式开发-处理器
  10. 《吴军-信息论40讲》摘录
  11. java cron在线_在线cron生成器
  12. ant安装配置使用介绍及eclipse中使用
  13. Jenkins自动化部署学习笔记(二、在Windows系统上使用Jenkins.war直接运行 )
  14. 【excel】如何进行数据排序
  15. 企业怎样顺利实施ERP管理系统?
  16. 微信小程序支付退款功能
  17. 【CVPR 2021】Knowledge Review:知识蒸馏新解法
  18. 汽车动力总成-基于GCAir和GCKontrol的TCU硬件在环HiL测试
  19. Intel RealSense Viewer软件工具键英文翻译
  20. mybatis自动建表oracle,利用mybatis-generator自动生成代码 - 菩提树下的杨过 - 博客园...

热门文章

  1. 一篇搞定,分布式系统中唯一主键生成
  2. 深度解析 | 基于DAG的分布式任务调度平台:Maat
  3. 真实感皮肤渲染技术总结
  4. pyecharts基础系列总结(含全系列文章路径)
  5. 真正的云主机到底是什么样的?
  6. 《Redis深度历险:核心原理和应用实践》千帆竞发——分布式锁
  7. vscode中go插件配置
  8. 「SDOI2016」储能表(数位dp)
  9. ubuntu部署git
  10. nodeJs配置相关以及JSON.parse