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. URAL 1557 Network Attack 图论,连通性,tarjain,dfs建树,分类讨论 难度:2

    http://acm.timus.ru/problem.aspx?space=1&num=1557 1557. Network Attack Time limit: 2.0 secondMem ...

  2. 二进制包形式安装mysql5.7.17

    mysql5.7与mysql5.5的安装方式有些区别,如果按照5.5的方式来安装5.7就会有很多报错信息,下面介绍mysql5.7.17的二进制安装方式. 首先安装依赖包: yum -y instal ...

  3. IOS开发使用GCD后台运行

    什么是GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法.该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中.GCD ...

  4. java面试题大纲

    跳槽时时刻刻都在发生,但是我建议大家跳槽之前,先想清楚为什么要跳槽.切不可跟风,看到同事一个个都走了,自己也盲目的开始面试起来(期间也没有准备充分),到底是因为技术原因(影响自己的发展,偏移自己规划的 ...

  5. 2017《Java技术》预备作业01

    2017<Java技术>预备作业 1.学习使用MarkDown 本学期的随笔都将使用MarkDown格式,要求熟练掌握MarkDown语法,学会如何使用标题,插入超链接,列表,插入图片,插 ...

  6. 【排序】堆排序,C++实现

    原创文章,转载请注明出处! 博客文章索引地址 博客文章中代码的github地址 # 预备知识     堆是一种特殊的树形数据结构,即完全二叉树.堆分为大根堆和小根堆,大根堆为根节点的值大于两个子节点的 ...

  7. save the transient instance before flushing错误解决办法 【待完善】

    近日在项目中遇到以下错误,着实郁闷了一把: org.hibernate.TransientObjectException: object references an unsaved transient ...

  8. 关于java日期

    时间戳转为yyyy-MM-dd SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String formatDa ...

  9. 异常处理过程和异常处理的执行顺序(针对try{}catch{}finally{}而言)

    1.异常的处理方式有两种分别为:try{}catch{}finally{}和throws下面简单说一下这两者的区别和联系. 2.出现异常之后如果没有进行捕获处理系统就会直接将这个异常栈的跟踪信息直接打 ...

  10. 在使用windows调用Hadoop 错误 /bin/bash: line 0: fg: no job control一般解决方法

    在使用windows调用Hadoop yarn平台的时候,一般都会遇到如下的错误: 2014-05-28 17:32:19,761 WARN org.apache.hadoop.yarn.server ...