题目大意:
  给你一个$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)$。

 #include<list>
#include<cstdio>
#include<cctype>
typedef long long int64;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=;
bool s[N];
int64 w[N];
int m,last[N];
std::list<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
class SegmentTree {
private:
struct Node {
int cnt;
int64 sum;
Node *left,*right;
};
public:
Node *root[N];
void modify(Node *&p,const int &b,const int &e,const int &l,const int &r,const int &x,const int &y) {
p=p?:new Node();
p->cnt+=x;
if(b==l&&e==r) {
p->sum+=y;
return;
}
const int mid=(b+e)>>;
if(l<=mid) modify(p->left,b,mid,l,std::min(mid,r),x,y);
if(r>mid) modify(p->right,mid+,e,std::max(mid+,l),r,x,y);
}
void merge(Node *&p,Node *const &q,const int &b,const int &e,const int &id) {
if(!p||!q) {
p=p?:q;
return;
}
w[id]+=p->cnt*q->sum+q->cnt*p->sum;
p->cnt+=q->cnt;
p->sum+=q->sum;
const int mid=(b+e)>>;
merge(p->left,q->left,b,mid,id);
merge(p->right,q->right,mid+,e,id);
delete q;
}
};
SegmentTree t;
void dfs(const int &x,const int &par) {
for(std::list<int>::iterator i=e[x].begin();i!=e[x].end();i++) {
const int &y=*i;
if(y==par) continue;
dfs(y,x);
t.merge(t.root[x],t.root[y],,m,x);
}
}
int main() {
const int n=getint();m=getint();
for(register int i=;i<=n;i++) {
last[i]=s[i]=getint();
}
for(register int i=;i<n;i++) {
add_edge(getint(),getint());
}
for(register int i=;i<=m;i++) {
const int opt=getint(),u=getint();
if(opt==) {
t.modify(t.root[u],,m,i,i,,);
if(s[u]) w[u]+=u;
}
if(opt==) {
if(s[u]^=) {
last[u]=i;
} else {
if(i!=) t.modify(t.root[u],,m,last[u],i-,,u);
}
}
}
for(register int i=;i<=n;i++) {
if(s[i]) t.modify(t.root[i],,m,last[i],m,,i);
}
dfs(,);
for(register int i=;i<=n;i++) printf("%lld\n",w[i]);
return ;
}

[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. 网络流24题:P2762 太空飞行计划问题

    P2762 太空飞行计划问题 题目背景 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,E ...

  2. leetcode 【 Rotate Image 】python 实现

    题目: You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwis ...

  3. PHP PDO fetch() 详解

    环境:(PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0) PDOStatement::fetch — 从结果集中获取下一行 说明 PDOStatement ...

  4. Leetcode 654.最大二叉树

    最大二叉树 给定一个不含重复元素的整数数组.一个以此数组构建的最大二叉树定义如下: 二叉树的根是数组中的最大元素. 左子树是通过数组中最大值左边部分构造出的最大二叉树. 右子树是通过数组中最大值右边部 ...

  5. 在同一个sql语句中如何写不同条件的count数量 (转)

    end) end)"描述名称2" from 表名 t

  6. IO Streams:对象流

    简介 正如数据流支持原始数据类型的I / O一样,对象流支持对象的I / O.标准类中的大多数但不是全部都支持对象的序列化.那些实现标记接口Serializable的那些. 对象流类是ObjectIn ...

  7. 【bzoj3277/bzoj3473】串/字符串 广义后缀自动机

    题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来n行每行一个 ...

  8. hihoCoder #1783 又一个重复计数

    题目大意 给定一个长度为 $n$ 的字符串 $S$,定义函数 $f(S)$ 表示 $S$ 的不同回文子串的个数.对于 $1\le l \le r \le n$,定义 $S[l,r]$ 为字符串 $S$ ...

  9. canvas图片跨域问题

    canvas的drawImage使用跨域图片时候,会报错,解决方法如下: 1. 使用base64替换跨域图片 如果图片不大,且只有几张,可以使用base64,来代替跨域引用图片. 2. 设置image ...

  10. bzoj 合集 1079 1791 1876 2208 2306

    1079 记忆化瞎搞吧,[a][b][c][d][e][l]表示当前有能涂1次的油漆a个,能涂2次的b个….前一个颜色为l,再搞下转移就行了. 1791 基环树上找直径 1876 高精度 2208 看 ...