传送门

题意:写一个数据结构,支持森林上:连边、删边、翻转点的颜色(黑白)、查询以某一点为根的某棵树上所有黑色点到根的距离和。$\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. ionic3 细节注意

    一.图标和splash大小不一样 icon图标的大小尽量为1024*1024,并且不能为圆角. splash图片的大小尽量为2732*2732,ionic1的大小为2208*2208

  2. Linux 学习笔记之超详细基础linux命令 Part 3

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 2----------------- ...

  3. (后端)SQL Server日期时间函数

    转自博客园: 1.获取当前日期GetDate getdate()函数以datetime数据类型的格式返回当前SQLServer服务器所在计算机的日期和时间.其语法格式为getdate().返回值舍入到 ...

  4. Info.plist的CFBundleIdentifier、CFBundleName、BundleDisplayName

    plist关键字段: CFBundleIdentifier:应用包名.唯一标识 CFBundleVersion:文件版本号,可以每次发版本递增 CFBundleShortVersionString:a ...

  5. [20180614]删除bootstrap$记录无法启动2.txt

    [20180614]删除bootstrap$记录无法启动2.txt --//前几天看链接http://www.xifenfei.com/2018/05/willfully-delete-bootstr ...

  6. SQL Server 临时表和表变量系列之选择篇

    原文地址:https://yq.aliyun.com/articles/69187 摘要: # 摘要 通过前面的三篇系列文章,我们对临时表和表变量的概念.对比和认知误区已经有了非常全面的认识.其实,我 ...

  7. Solr全文检索

    1.Solr的安装 .环境要求 jdk1.+tomcat8+solr5.5.0 .将以上的软件包上传到服务器 . 安装tomcat8(解压文件) tar -zxvf apache-tomcat-.ta ...

  8. 17秋 软件工程 团队第五次作业 Alpha Scrum5

    17秋 软件工程 团队第五次作业 Alpha Scrum5 今日完成的任务 世强:消息通知管理列表页界面编写,下拉加载效果: 港晨:编写登录界面: 树民: 伟航:学习了flask_restful框架的 ...

  9. MyCat读写分离、分库分表

    系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库等都是系统发展迟早会遇到的技术问题问题.Mycat是一 ...

  10. dirty_background_ration 与 /proc/sys/vm/dirty_ratio

    wappiness的值的大小对如何使用swap分区是有着很大的联系的.swappiness=0的时候表示最大限度使用物理内存,然后才是 swap空间,swappiness=100的时候表示积极的使用s ...