Description

给你一棵包含N个节点的树,设每条边一开始的边权为0,现在有两种操作:
 
1)给出参数U,V,C,表示把U与V之间的路径上的边权变成C(保证C≥0)
 
2)给出参数U,V,C,表示把U与V之间的路径上的边权加上C。但是如果U至V之间路径某条边的边权加上C小于0,那么C=这条边的边权的相反数。
 
你需要统计出每次一操作过后树中边权为0的边有多少条。

Input

第一行两个整数N,M,分别表示表示节点个数与操作数。
接下来N-1行每行两个整数X,Y表示X,Y之间有一条边。
接下来M行每行4个整数P,U,V,C,P表示操作类型,U,V,C的意义见题目描述。

Output

输出文件包括M行,每行一个整数,表示边权为0的边的个数。
树链剖分+线段树维护一下区间最小值和个数、覆盖标记、加法标记
#include<cstdio>
#include<algorithm>
typedef long long i64;
const int N=;
const i64 fil_0=1ll<<;
char buf[],*ptr=buf-;
int _(){
int x=,c=*++ptr,f=;
while(c<)c=='-'&&(f=-),c=*++ptr;
while(c>)x=x*+c-,c=*++ptr;
return x*f;
}
int n,m,es[N*],enx[N*],e0[N],ep=,ans=;
int fa[N],sz[N],dep[N],top[N],son[N],id[N],idp=;
int _l,_r;
i64 _a;
struct node{
node*lc,*rc;
i64 mn,fil,a;
int L,R,mc;
int c0(){
return mn?:mc;
}
void _fil(i64 x){
mn=fil=x;
mc=R-L+;
a=;
}
void _add(i64 x){
if(fil!=fil_0)fil+=x;
mn+=x;a+=x;
}
void fils(){
if(_l<=L&&R<=_r){
_fil(_a);
return;
}
dn();
int M=L+R>>;
if(_l<=M)lc->fils();
if(_r>M)rc->fils();
up();
}
void mns(){
if(mn>=_a)return;
if(_l<=L&&R<=_r){
_a=mn;
return;
}
dn();
int M=L+R>>;
if(_l<=M)lc->mns();
if(_r>M)rc->mns();
}
void adds(){
if(_l<=L&&R<=_r){
_add(_a);
return;
}
dn();
int M=L+R>>;
if(_l<=M)lc->adds();
if(_r>M)rc->adds();
up();
}
void dn(){
if(a){
lc->_add(a);
rc->_add(a);
a=;
}
if(fil!=fil_0){
lc->_fil(fil);
rc->_fil(fil);
fil=fil_0;
}
}
void up(){
mn=lc->mn<rc->mn?lc->mn:rc->mn;
mc=;
if(mn==lc->mn)mc+=lc->mc;
if(mn==rc->mn)mc+=rc->mc;
}
}ns[N*],*np=ns,*rt[N];
node*build(int L,int R){
node*w=np++;
w->L=L;w->R=R;
if(L!=R){
int M=L+R>>;
w->lc=build(L,M);
w->rc=build(M+,R);
w->up();
}else{
w->mn=;w->mc=;
w->fil=fil_0;
}
return w;
}
#define F(a,b) ans-=a->c0(),a->b(),ans+=a->c0()
void fils(int x,int y,i64 c){
int a=top[x],b=top[y];
_a=c;
while(a!=b){
if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);
_l=id[a],_r=id[x];
F(rt[a],fils);
x=fa[a];a=top[x];
}
if(dep[x]>dep[y])std::swap(x,y);
_l=id[x]+,_r=id[y];
if(_l<=_r)F(rt[top[x]],fils);
}
void mns(int x,int y,i64 c){
int a=top[x],b=top[y];
_a=c;
while(a!=b){
if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);
_l=id[a],_r=id[x];
rt[a]->mns();
x=fa[a];a=top[x];
}
if(dep[x]>dep[y])std::swap(x,y);
_l=id[x]+,_r=id[y];
if(_l<=_r)rt[top[x]]->mns();
}
void adds(int x,int y,i64 c){
mns(x,y,-c);
_a*=-;
int a=top[x],b=top[y];
while(a!=b){
if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);
_l=id[a],_r=id[x];
F(rt[a],adds);
x=fa[a];a=top[x];
}
if(dep[x]>dep[y])std::swap(x,y);
_l=id[x]+,_r=id[y];
if(_l<=_r)F(rt[top[x]],adds);
}
void f1(int w,int pa){
dep[w]=dep[fa[w]=pa]+;
sz[w]=;
for(int i=e0[w];i;i=enx[i]){
int u=es[i];
if(u!=pa){
f1(u,w);
sz[w]+=sz[u];
if(sz[u]>sz[son[w]])son[w]=u;
}
}
}
void f2(int w,int tp){
top[w]=tp;
id[w]=++idp;
if(son[w])f2(son[w],tp);
else rt[tp]=build(id[tp],id[w]);
for(int i=e0[w];i;i=enx[i]){
int u=es[i];
if(u!=fa[w]&&u!=son[w])f2(u,u);
}
}
int main(){
buf[fread(buf,,sizeof(buf),stdin)]=;
n=_();m=_();
for(int i=,a,b;i<n;++i){
a=_();b=_();
es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
}
f1(,);f2(,);
ans=n-;
for(int i=,o,u,v,c;i<m;++i){
o=_();u=_();v=_();c=_();
if(o==)fils(u,v,c);
else adds(u,v,c);
printf("%d\n",ans);
}
return ;
}

bzoj4353: Play with tree的更多相关文章

  1. BZOJ4353 Play with tree[树剖]

    复习几乎考不到的树剖.维护min以及min个数,打set和add标记即可,注意set优先级优于add. #include<iostream> #include<cstdio> ...

  2. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

  3. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  4. SAP CRM 树视图(TREE VIEW)

    树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...

  5. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

  6. 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  7. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  8. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  9. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

随机推荐

  1. Prism5.0开发人员指南内容(纯汉语版)

    Prism指南包含以下内容: 下载并安装Prism Prism5.0新内容 介绍 初始化应用程序 组件间的依赖管理 模块化应用程序开发 实现MVVM模式 进击的MVVM 组合式用户界面 导航 松耦合组 ...

  2. Markdown_04_折叠语法

    目录 一.折叠语法 参考资料 一.折叠语法 主要使用的是 html5的 details标签 (1)示例如下: <details> <summary>折叠文本</summa ...

  3. Linux真随机数的生成

    今天看<白帽子讲WEB安全>一书,看到笔者谈到Linux如何实现真随机数生成,感觉非常有用,记录下来 #include<iostream> using namespace st ...

  4. java集合运算:求交集,并集,集合差

    今天突然想用Java实现如何用集合实现交集,并集和差集的运算了!主要是看Python语言的时候想起来的. 实现主要使用的Set集合,Set集合的特点是集合内的元素不可重复. 具体代码如何: packa ...

  5. vue.js 源代码学习笔记 ----- core lifecycle

    /* @flow */ import config from '../config' import Watcher from '../observer/watcher' import { mark, ...

  6. 迭代器、foreach循环、泛型集合

    集合的迭代 语法:Iterator<Object> it=集合.iterator(); while(it.hasNext()){ Object obj=it.next(); } is.ha ...

  7. 从头搭建一个React应用

    node,webpack这些就不一一介绍怎么安装了,默认大家都知道. 一.npm install -g create-react-app 首先全局安装react的脚手架工具 create-react- ...

  8. 实现DQN算法玩CartPole

    先安装tensorflow 1.2版本和python 3.6, 接着安装: numpy-1.13.1+mkl-cp36-cp36m-win_amd64.whl 的版本,这个是windows下的,如果l ...

  9. ng-bind 拼接字符标签

  10. JSCover(查看代码覆盖率)

    1. [文档](http://tntim96.github.io/JSCover/manual/manual.xml)1. [下载](https://sourceforge.net/projects/ ...