传送门

题意:写一个数据结构,支持森林上:连边、删边、翻转点的颜色(黑白)、查询以某一点为根的某棵树上所有黑色点到根的距离和。$\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. web全栈架构师[笔记] — 02 数据交互

    数据交互 一.http协议 基本特点 1.无状态的协议 2.连接过程:发送连接请求.响应接受.发送请求 3.消息分两块:头.体 http和https 二.form 基本属性 action——提交到哪儿 ...

  2. Network-Emulator Network-Emulator-Toolkit网络模拟器使用详细介绍

    Network-Emulator-Toolkit网络模拟器使用详细介绍 by:授客 QQ:1033553122 原理介绍 图1 如上图,一个ADSL用户通过modem连接到网络,通过网络应用如IE,M ...

  3. 2018下半年Android面试历程

    个人看法:可以总结下他的面试经历以及涉及到的面试题 下面开始正文吧: 从今年下半年以来就开始在杭州准备简历找工作了,原因基本都懂的,没多少工资,投递简历的渠道是Boss,偶尔也在拉钩上投递,刚开始把简 ...

  4. Android事件总线(四)源码解析otto

    前言 上一篇文章中讲到了otto的用法,这一篇我们来讲一下otto的源码.可能有人觉得otto过时了,但是通过源码我们学习的是高手设计otto时的设计理念,这种设计理念是不过时的. otto各个类的作 ...

  5. 【Java入门提高篇】Day21 Java容器类详解(四)ArrayList源码分析

    今天要介绍的是List接口中最常用的实现类——ArrayList,本篇的源码分析基于JDK8,如果有不一致的地方,可先切换到JDK8后再进行操作. 本篇的内容主要包括这几块: 1.源码结构介绍 2.源 ...

  6. JavaScript大杂烩7 - 理解内置集合

    JavaScript内置了很多对象,简单的类型如String,Number,Boolean (相应的"值类型"拥有相同的方法),复杂一点的如Function,Object,Arra ...

  7. FUSE 用户空间文件系统 (Filesystem in Userspace)

    FUSE 仓库 Wiki FUSE 性能评测 关于Fuse文件系统: FUSE (Filesystem in Userspace) is an interface for userspace prog ...

  8. java web中java和python混合使用

    利用java web技术展示python算法处理后的数据 工具/原料   myeclipse10 pycharm+Anaconda2 方法/步骤     首先安装配置好pycharm+Anaconda ...

  9. if语句的嵌套以及条件运算符和条件表达式(初学者)

    1.当if语句中的执行语句又是if语句时,则构成了if语句的嵌套情形. 其一般形式可表示为: if() { if()……; } 或: if() if()语句1: else 语句2: else if() ...

  10. C#异步编程のawait和async关键字来写异步程序

    一.await和async关键字 .Net平台不断推出了新的异步编程模型,在.net4.5中加入了关键字await和async,顾名思义,await是指方法执行可等待,即可挂起直到有结果(不是必须立即 ...