题目大意:
  给你一个$n(n\leq300000)$个结点的以$1$为根的树,结点有黑白两种颜色,每个点初始权值为$0$。进行以下2种共$m(m\leq300000)$次操作:
    1.给定结点$u$,对于所有的黑点$v$,令${\rm LCA}(u,v)$的权值加上$v$;
    2.改变$u$的颜色。

思路:
  考虑没有操作2的情况,我们可以记录所有结点被询问的次数和所有黑点的编号。最后统计答案时,只需要一个树形DP,求出每个子树内被询问的次数$cnt$和所有黑点的编号之和$sum$即可。$w[x]=\sum cnt[y]\times(sum[x]-sum[y])$。
  考虑加上操作2,本质上就是多了一个表示时间的维度,考虑使用线段树降维,树形DP时只需要线段树合并更新答案即可。时间复杂度$O(n\log n)$。

  1. #include<list>
  2. #include<cstdio>
  3. #include<cctype>
  4. typedef long long int64;
  5. inline int getint() {
  6. register char ch;
  7. while(!isdigit(ch=getchar()));
  8. register int x=ch^'';
  9. while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
  10. return x;
  11. }
  12. const int N=;
  13. bool s[N];
  14. int64 w[N];
  15. int m,last[N];
  16. std::list<int> e[N];
  17. inline void add_edge(const int &u,const int &v) {
  18. e[u].push_back(v);
  19. e[v].push_back(u);
  20. }
  21. class SegmentTree {
  22. private:
  23. struct Node {
  24. int cnt;
  25. int64 sum;
  26. Node *left,*right;
  27. };
  28. public:
  29. Node *root[N];
  30. void modify(Node *&p,const int &b,const int &e,const int &l,const int &r,const int &x,const int &y) {
  31. p=p?:new Node();
  32. p->cnt+=x;
  33. if(b==l&&e==r) {
  34. p->sum+=y;
  35. return;
  36. }
  37. const int mid=(b+e)>>;
  38. if(l<=mid) modify(p->left,b,mid,l,std::min(mid,r),x,y);
  39. if(r>mid) modify(p->right,mid+,e,std::max(mid+,l),r,x,y);
  40. }
  41. void merge(Node *&p,Node *const &q,const int &b,const int &e,const int &id) {
  42. if(!p||!q) {
  43. p=p?:q;
  44. return;
  45. }
  46. w[id]+=p->cnt*q->sum+q->cnt*p->sum;
  47. p->cnt+=q->cnt;
  48. p->sum+=q->sum;
  49. const int mid=(b+e)>>;
  50. merge(p->left,q->left,b,mid,id);
  51. merge(p->right,q->right,mid+,e,id);
  52. delete q;
  53. }
  54. };
  55. SegmentTree t;
  56. void dfs(const int &x,const int &par) {
  57. for(std::list<int>::iterator i=e[x].begin();i!=e[x].end();i++) {
  58. const int &y=*i;
  59. if(y==par) continue;
  60. dfs(y,x);
  61. t.merge(t.root[x],t.root[y],,m,x);
  62. }
  63. }
  64. int main() {
  65. const int n=getint();m=getint();
  66. for(register int i=;i<=n;i++) {
  67. last[i]=s[i]=getint();
  68. }
  69. for(register int i=;i<n;i++) {
  70. add_edge(getint(),getint());
  71. }
  72. for(register int i=;i<=m;i++) {
  73. const int opt=getint(),u=getint();
  74. if(opt==) {
  75. t.modify(t.root[u],,m,i,i,,);
  76. if(s[u]) w[u]+=u;
  77. }
  78. if(opt==) {
  79. if(s[u]^=) {
  80. last[u]=i;
  81. } else {
  82. if(i!=) t.modify(t.root[u],,m,last[u],i-,,u);
  83. }
  84. }
  85. }
  86. for(register int i=;i<=n;i++) {
  87. if(s[i]) t.modify(t.root[i],,m,last[i],m,,i);
  88. }
  89. dfs(,);
  90. for(register int i=;i<=n;i++) printf("%lld\n",w[i]);
  91. return ;
  92. }

[XJOI-NOI2015-13-C]白黑树的更多相关文章

  1. 学军NOI训练13 T3 白黑树

    唉,大学军有自己的OJ就是好,无限orz 只有周六的比赛是开放的囧,这场比赛最后因为虚拟机卡住没有及时提交…… 否则就能让大家看到我有多弱了…… 前两题题解写的很详细,可以自己去看,我来随便扯扯T3好 ...

  2. [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】

    题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...

  3. [XJOI NOI2015模拟题13] B 最小公倍数 【找规律】

    题目链接:XJOI - NOI2015-13 - B 题目分析 通过神奇的观察+打表+猜测,有以下规律和性质: 1) 删除的 n 个数就是 1~n. 2) 当 c = 2 时,如果 n + 1 是偶数 ...

  4. [XJOI NOI2015模拟题13] A 神奇的矩阵 【分块】

    题目链接:XJOI NOI2015-13 A 题目分析 首先,题目定义的这种矩阵有一个神奇的性质,第 4 行与第 2 行相同,于是第 5 行也就与第 3 行相同,后面的也是一样. 因此矩阵可以看做只有 ...

  5. [Data Structure] 红黑树( Red-Black Tree ) - 笔记

    1.  红黑树属性:根到叶子的路径中,最长路径不大于最短路径的两倍. 2. 红黑树是一个二叉搜索树,并且有 a. 每个节点除了有左.右.父节点的属性外,还有颜色属性,红色或者黑色. b. ( 根属性 ...

  6. 红黑树red-black tree

    书籍:<算法导论>第13章 红黑树性质:1. 每个节点要么red要么black.2. 根节点是black节点.3. 叶子节点是black节点.4. red节点的左右儿子节点都是black节 ...

  7. C++基础_总结

    (1)多态性都有哪些?(静态和动态,然后分别叙述了一下虚函数和函数重载) 多态分为两种:静态和动态.静态主要包括函数重载和模板:动态主要是依靠虚函数实现的. 静态联编:重载函数不加virtual关键字 ...

  8. PP66 EEPPPPMM SSyysstteemm AAddmmiinniissttrraattiioonn GGuuiiddee 16 R1

    ※★◆●PP66 EEPPPPMM SSyysstteemm AAddmmiinniissttrraattiioonn GGuuiiddee 16 R1AApprriill 22001166Conte ...

  9. Mac生存手册

    最近刚从Linux转到了Mac系统上,感觉好的地方是再也不折腾了,什么GNOME, KDE, XFCE,各种发行版本都远离我而去了.当然Mac下很多好软件都是要付费的,我只能绕着走了: 1. 命令行, ...

随机推荐

  1. Android stadio 电脑连上手机可以识别,但是连不上Android stadio

    原来是因为电脑没有装Android 手机驱动,我电脑刚装了系统. 很多驱动没有装.我有一个联想驱动管理,提示我装Android手机驱动.装完之后,就可以识别到手机了. 如果你的手机在电脑不识别,那么装 ...

  2. XX公司在线笔试题编程题之一

    题目: #include <iostream> #include <vector> #include <string> #include <list> ...

  3. 使用 Pinup,PinupManager 在 XNA 中创建贴图(十七)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  4. spaCy 并行分词

    spaCy 并行分词 在使用spacy的时候,感觉比nltk慢了许多,一直在寻找并行化的方案,好在找到了,下面给出spaCy并行化的分词方法使用示例: import spacy nlp = spacy ...

  5. POJ-1087 二分图匹配,最大流。

                                                      A Plug for UNIX 题意很迷,不过很水. 题意:一个房间有m个插座,每个插座有一个型号, ...

  6. 优化脚本性能 Optimizing Script Performance

    This page gives some general hints for improving script performance on iOS. 此页面提供了一些一般的技巧,提高了在iOS上的脚 ...

  7. JDBC 学习笔记(十二)—— DataSource

    在 JDBC 的实现过程中,最消耗资源的从来不是执行 SQL 之类的过程,而是获取-释放 数据库连接 Connection 的过程. 之前通过 DriverManager 获得的数据库连接对象,每一个 ...

  8. AngularJs之HelloWorld

    <!DOCTYPE html> <html lang="en" ng-app> <head> <meta charset="UT ...

  9. 【bzoj2427】[HAOI2010]软件安装 Tarjan+树形背包dp

    题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现 ...

  10. POJ 2723 Get Luffy Out(2-SAT+二分答案)

    Get Luffy Out Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8851   Accepted: 3441 Des ...