传送门

题意:写一个数据结构,支持森林上:连边、删边、翻转点的颜色(黑白)、查询以某一点为根的某棵树上所有黑色点到根的距离和。$\text{点数} \leq 10^5 , \text{操作数} \leq 3 \times 10^5$


连边删边不用说就是$LCT$,而边有边权,显然需要化边为点进行操作

考虑如何维护最后一个信息。考虑$LCT$中$Splay$上的某一棵子树,$Splay$的根为$x$,其左子树为$lson$,右子树为$rson$,虚子树统一称为$son$

如果我们已经计算好了$lson,rson,son$的答案,如何计算$x$的答案?

因为$Splay$上对应原树的一条链,所以:

①$rson$与$son$中的黑点在需要经过左子树中的所有边和$x$(如果$x$代表一条边),所以答案需要加上$rson$与$son$中的黑点总数$\times\,$($x$代表的边的边权$+lson$中的实链边权总和)

②如果$x$代表一个黑点,它需要经过左子树中的所有边,所以答案需要加上$lson$中的实链边权总和

③答案再加上$lson,rson,son$的答案即可。

所以我们需要维护子树的边权总和、黑点总数,才能够计算答案。

需要注意以下几点:

①边权总和不需要将虚子树的计算在内(显然虚子树内的点都在虚子树上传的时候计算完了答案,所以在其他点上不会产生贡献),只需要把实链的计算上去

②因为需要$makeroot$操作,所以你还要记录将左右子树反过来之后的答案,这样才能正确下传标记

③注意一点:翻转左右子树对虚子树内部答案没有影响,所以虚子树答案直接上传不经过翻转的即可

 #include<bits/stdc++.h>
 #define lch Tree[x].ch[0]
 #define rch Tree[x].ch[1]
 #define int long long
 //This code is written by Itst
 using namespace std;

 inline int read(){
     ;
     ;
     char c = getchar();
     while(c != EOF && !isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(c != EOF && isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }

 ;
 struct node{
     ] , size , non_size;
     long long val , sumE , sumL , non_sum , sumR;
     bool mark , col;
 }Tree[MAXN << ];
 int N , M , K , cntNode;

 inline bool nroot(int x){
     ] == x || Tree[Tree[x].fa].ch[] == x;
 }

 inline bool son(int x){
     ] == x;
 }

 inline void pushup(int x){
     Tree[x].size = Tree[lch].size + Tree[rch].size + Tree[x].non_size + Tree[x].col;
     Tree[x].sumE = Tree[lch].sumE + Tree[rch].sumE + Tree[x].val;
     Tree[x].sumL = Tree[lch].sumL + Tree[rch].sumL + Tree[x].non_sum +(Tree[rch].size + Tree[x].non_size + Tree[x].col) * (Tree[x].val + Tree[lch].sumE);
     Tree[x].sumR = Tree[lch].sumR + Tree[rch].sumR + Tree[x].non_sum + (Tree[lch].size + Tree[x].non_size + Tree[x].col) * (Tree[x].val + Tree[rch].sumE);
 }

 inline void rotate(int x){
     bool f = son(x);
     ];
     if(nroot(y))
         Tree[z].ch[son(y)] = x;
     Tree[x].fa = z;
     Tree[x].ch[f ^ ] = y;
     Tree[y].fa = x;
     Tree[y].ch[f] = w;
     if(w)
         Tree[w].fa = y;
     pushup(y);
 }

 inline void reverse(int x){
     Tree[x].mark ^= ;
     swap(lch , rch);
     swap(Tree[x].sumL , Tree[x].sumR);
 }

 inline void pushdown(int x){
     if(Tree[x].mark){
         reverse(lch);
         reverse(rch);
         Tree[x].mark = ;
     }
 }

 void pushdown_all(int x){
     if(nroot(x))
         pushdown_all(Tree[x].fa);
     pushdown(x);
 }

 inline void Splay(int x){
     pushdown_all(x);
     while(nroot(x)){
         if(nroot(Tree[x].fa))
             rotate(son(Tree[x].fa) == son(x) ? Tree[x].fa : x);
         rotate(x);
     }
     pushup(x);
 }

 inline void access(int x){
      ; x ; y = x , x = Tree[x].fa){
         Splay(x);
         Tree[x].non_size = Tree[x].non_size + Tree[Tree[x].ch[]].size - Tree[y].size;
         Tree[x].non_sum = Tree[x].non_sum + Tree[Tree[x].ch[]].sumL - Tree[y].sumL;
         Tree[x].ch[] = y;
         pushup(x);
     }
 }

 inline void makeroot(int x){
     access(x);
     Splay(x);
     reverse(x);
 }

 inline void split(int x , int y){
     makeroot(x);
     access(y);
     Splay(y);
 }

 inline void _link(int x , int y){
     makeroot(x);
     makeroot(y);
     Tree[y].non_size += Tree[x].size;
     Tree[y].non_sum += Tree[x].sumL;
     Tree[x].fa = y;
     pushup(y);
 }

 inline void link(int x , int y , int val){
     Tree[++cntNode].val = val;
     _link(x , cntNode);
     _link(y , cntNode);
 }

 inline void cut(int x , int y){
     split(y , x);
     if(Tree[y].fa == x){
         Tree[y].ch[] = ;
         pushup(y);
     }
     else
         Tree[y].fa = Tree[Tree[y].fa].ch[] = ;
     lch = Tree[lch].fa = ;
     pushup(x);
 }

 inline void query(int x){
     makeroot(x);
     printf("%lld\n" , Tree[x].sumL);
 }

 inline char getc(){
     char c = getchar();
     while(!isupper(c))
         c = getchar();
     return c;
 }

 signed main(){
 #ifndef ONLINE_JUDGE
     freopen("558.in" , "r" , stdin);
     freopen("558.out" , "w" , stdout);
 #endif
     N = read();
     M = read();
     K = read();
     cntNode = N;
     int a , b , w;
     while(M--){
         a = read();
         b = read();
         w = read();
         link(a , b , w);
     }
     while(K--)
         switch(getc()){
         case 'L':
             a = read();
             b = read();
             w = read();
             link(a , b , w);
             break;
         case 'C':
             a = read();
             b = read();
             cut(a , b);
             break;
         case 'F':
             a = read();
             makeroot(a);
             Tree[a].col ^= ;
             pushup(a);
             break;
         case 'Q':
             query(read());
             break;
         }
     ;
 }

LOJ558 我们的 CPU 遭到攻击 LCT的更多相关文章

  1. loj558 「Antileaf's Round」我们的CPU遭到攻击

    考完了可以发题解了. 做法是link-cut tree维护子树信息,并不需要维护黑树白树那些的. 下面是一条重链: 如果4是根的话,那么在splay上是这样的: 在splay中,子树的信息都已经计算完 ...

  2. LCT总结——应用篇(附题单)(LCT)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--概念篇戳这里 题单 灰常感谢XZY巨佬提供的强力资磁!(可参考XZY巨佬的博客总结) 题单对于系 ...

  3. 【转载】LCT题单

    本篇博客的题单转载自FlashHu大佬的博客:LCT总结--应用篇(附题单)(LCT). 关于\(LCT\)可以查看这篇博客:\(LCT\)入门. 这里面有些题解的链接是空链接,尚未补全. 维护链信息 ...

  4. LCT 入门

    这是一份 \(\rm LCT\) 入门总结. 关于 \(\rm LCT\) 的复杂度这里不会提及,只会记录 \(\rm LCT\) 的基本操作和经典例题,但神奇的 \(\rm LCT\) 虽然常数巨大 ...

  5. 【H3C交换机】cpu各个进程的详细说明

    display cpu-usage命令用来查看设备CPU占用率的统计信息,以及各个进程的cpu占用率. 各个进程详细说明如下,不同软件版本.盒式和框式的cpu进程略有不同,详细信息可以查看手册中的命令 ...

  6. 关于 Spring Security 5 默认使用 Password Hash 算法

    账户密码存储的安全性是一个很老的话题,但还是会频频发生,一般的做法是 SHA256(userInputpwd+globalsalt+usersalt) 并设置密码时时要求长度与大小写组合,一般这样设计 ...

  7. A Survey on the Security of Stateful SDN Data Planes

    论文摘要: 本文为读者提供新兴的SDN带状态数据平面,集中关注SDN数据平面编程性带来的隐患. I部分 介绍 A.带状态SDN数据平面的兴起 B.带状态数据平面带来的安全隐患 引出带状态数据平面的安全 ...

  8. Bitcoin: A Peer-to-Peer Electronic Cash System(比特币论文翻译)

    比特币历史: 2008年,比特币论文诞生 2009年1月,第一批比特币诞生 2011年4月,比特币价格第一次达到了1美元 2011年6月,涨到30美元,然后开始跌 2013年1月,4美元 2013年1 ...

  9. CVE-2019-0708 漏洞分析及相关测试

    在CVE-2019-0708公布后几天就已经尝试过复现该漏洞,但借助当时exp并没能成功复现反弹shell的过程遂放弃,故借助这次漏洞复现报告再来尝试复现该漏洞,因为还在大三学习中,有很多知识还没有掌 ...

随机推荐

  1. CSS 实现隐藏滚动条同时又可以滚动

    方法1: 利用 css 3 的新特性  -webkit-scrollbar, 但是这种方式只兼容chrome,不兼容 火狐 和 IE. /* for Chrome */ .content::-webk ...

  2. 安卓开发ScrollView嵌套ListView只显示一行

    在用列表控件做一个“更多功能”的界面的时候 <?xml version="1.0" encoding="utf-8"?> <ScrollVie ...

  3. axure工具的使用总结

    ---恢复内容开始--- Axure工具的使用 axure是什么? Axure RP是一款快速原型设计工具,它不需要任何编程或写代码基础,就可以设计出交互效果良好的产品原型,常用于互联网产品设计.网页 ...

  4. NoHttp封装--02 自定义请求

    bean实体类请求: 1.bean import java.io.Serializable; import com.alibaba.fastjson.annotation.JSONField; pub ...

  5. LDA背景资料

    [https://zhuanlan.zhihu.com/p/30226687] LDA模型的前世今生 在文本挖掘中,有一项重要的工作就是分析和挖掘出文本中隐含的结构信息,而不依赖任何提前标注的信息.L ...

  6. python常用模块之pickle

    python1个json模块和1个pickle模块都是用于序列化的模块. 其中前文介绍过json模块.json模块只能序列化普通字符,比如字典.列表等.但是如果是函数呢?json其实是无法序列化的.这 ...

  7. 基于 node 搭建博客系统(一)

    系统分为两端,分别实现. 管理员端: 功能 :个人信息,设置,发布随笔,随笔列表,删除随笔,查找,文章 等. 技术点:Boostrap + AdminLTE; 基于nodejs 实现的express ...

  8. 【PAT】B1074 宇宙无敌加法器(20 分)

    打一开始做就听人说这个难,吓得我把它放到了最后做,不过如此嘛. 这里说说样例的坑点 1.最后结果可能高位有0:例如样例结果07201 2.结果会进位, 3.有可能结果是0,(此处取决于你的输出方式) ...

  9. Unity Ulua1.03优化记录

    现在项目的框架是在2015年设计的,那时候Ulua还处于1.03版本,现在回头再看,Ulua已经迭代到1.25版本,中间引入带有wraper的cstolua,而后转向现有的toLua#版本. 随着版本 ...

  10. [ISE 14.7] _pn.exe 崩溃问题 点击浏览崩溃问题

    前言 装了大半天的ISE 14.7 结果新建工程的时候只要点击浏览文件夹,直接无响应,其实和其他_pn.exe崩溃是一样的. 解决方法 第一步:非常重要,进行文件备份,将"F:\Xilinx ...