4127: Abs

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 11  Solved: 5
[Submit][Status][Discuss]

Description

 给定一棵树,设计数据结构支持以下操作

    1 u v d  表示将路径 (u,v) 加d

    2 u v  表示询问路径 (u,v) 上点权绝对值的和

Input

第一行两个整数n和m,表示结点个数和操作数
接下来一行n个整数a_i,表示点i的权值

接下来n-1行,每行两个整数u,v表示存在一条(u,v)的边

接下来m行,每行一个操作,输入格式见题目描述

Output

对于每个询问输出答案

Sample Input

4 4
-4 1 5 -2
1 2
2 3
3 4
2 1 3
1 1 4 3
2 1 3
2 3 4

Sample Output

10
13
9

HINT

对于100%的数据,n,m <= 10^5 且 0<= d,|a_i|<= 10^8

  我们分开处理正数负数情况,注意加数为正,所以一个负数被加成正数最多发生O(n)次,我们需要实现的就是快速的判定是否有某个负数加成了正数,维护负数集合中的最大值和位置即可。如果负数集合的最大值大于0,那么我们求得最大值所在位置,然后暴力将它修改到正数集合即可。

  注意这道题INF取0x3f3f3f3f要出事。

  第一次写链剖的每个链单独建线段树版本,不是太难。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 210000
#define MAXT MAXN*4
#define MAXV MAXN
#define MAXE MAXN*2
#define INFL 0x3f3f3f3f3f3f3f3f
#define smid ((l+r)>>1)
#define abs(x) ((x)>0?x:-(x))
typedef long long qword;
inline int nextInt()
{
register char ch;
register int x=;
register bool f=false;
while (ch=getchar(),ch<'' || ch>'')f|=ch=='-';
while (x=x*+ch-'',ch=getchar(),ch<='' && ch>='');
return x*(f?-:);
}
struct sgt_node
{
int lc,rc;
int sd;
qword sv;
qword pls;
pair<qword,int> mx;
}sgt[MAXT];
int topt=;
int a[MAXN];
int b[MAXN];
void update(int now)
{
sgt[now].mx=max(sgt[sgt[now].lc].mx,sgt[sgt[now].rc].mx);
sgt[now].sd=sgt[sgt[now].lc].sd+sgt[sgt[now].rc].sd;
sgt[now].sv=sgt[sgt[now].lc].sv+sgt[sgt[now].rc].sv;
}
void make_plus(int now,int l,int r,qword delta)
{
sgt[now].sv+=(qword)sgt[now].sd*delta;
sgt[now].pls+=delta;
sgt[now].mx.first+=delta;
}
void down(int now,int l,int r)
{
if (sgt[now].pls)
{
make_plus(sgt[now].lc,l,smid,sgt[now].pls);
make_plus(sgt[now].rc,smid+,r,sgt[now].pls);
sgt[now].pls=;
}
}
void Build_sgt(int &now,int l,int r)
{
now=++topt;
if (l==r)
{
sgt[now].sd=b[l]<?-:;
sgt[now].sv=abs(b[l]);
if (b[l]<)
{
sgt[now].mx=make_pair(b[l],l);
}else
{
sgt[now].mx=make_pair(-INFL,-);
}
return ;
}
Build_sgt(sgt[now].lc,l,smid);
Build_sgt(sgt[now].rc,smid+,r);
update(now);
}
void Add_sgt(int now,int l,int r,int x,int y,int delta)
{
if (l==x && r==y)
{
make_plus(now,l,r,delta);
return ;
}
down(now,l,r);
if (y<=smid)
Add_sgt(sgt[now].lc,l,smid,x,y,delta);
else if (smid<x)
Add_sgt(sgt[now].rc,smid+,r,x,y,delta);
else
{
Add_sgt(sgt[now].lc,l,smid,x,smid,delta);
Add_sgt(sgt[now].rc,smid+,r,smid+,y,delta);
}
update(now);
}
void Modify_sgt(int now,int l,int r,int pos,qword v)
{
if (l==r)
{
if (v<)
sgt[now].mx=make_pair(v,l);
else
sgt[now].mx=make_pair(-INFL,-);
sgt[now].sd=v<?-:;
sgt[now].sv=abs(v);
sgt[now].pls=;
return ;
}
down(now,l,r);
if (pos<=smid)
Modify_sgt(sgt[now].lc,l,smid,pos,v);
else
Modify_sgt(sgt[now].rc,smid+,r,pos,v);
update(now);
}
pair<qword,int> Query_sgt_max(int now,int l,int r,int x,int y)
{
if (l==x && r==y)
{
return sgt[now].mx;
}
down(now,l,r);
if (y<=smid)
return Query_sgt_max(sgt[now].lc,l,smid,x,y);
else if (smid<x)
return Query_sgt_max(sgt[now].rc,smid+,r,x,y);
else
return max(Query_sgt_max(sgt[now].lc,l,smid,x,smid),
Query_sgt_max(sgt[now].rc,smid+,r,smid+,y));
}
qword Query_sgt_sum(int now,int l,int r,int x,int y)
{
if (l==x && r==y)
return sgt[now].sv;
down(now,l,r);
if (y<=smid)
return Query_sgt_sum(sgt[now].lc,l,smid,x,y);
else if (smid<x)
return Query_sgt_sum(sgt[now].rc,smid+,r,x,y);
else
return Query_sgt_sum(sgt[now].lc,l,smid,x,smid)+
Query_sgt_sum(sgt[now].rc,smid+,r,smid+,y);
}
struct Edge
{
int np;
Edge *next;
}E[MAXE],*V[MAXV];
int tope=-;
void addedge(int x,int y)
{
E[++tope].np=y;
E[tope].next=V[x];
V[x]=&E[tope];
}
int q[MAXN];
int depth[MAXN],top[MAXN],son[MAXN];
int pnt[MAXN],siz[MAXN];
int pos[MAXN],dfstime;
int spos[MAXN],tpos[MAXN];
void bfs(int now)
{
int head=-,tail=;
Edge *ne;
q[]=now;
depth[now]=;
while (head<tail)
{
now=q[++head];
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
pnt[ne->np]=now;
depth[ne->np]=depth[now]+;
q[++tail]=ne->np;
}
}
for (int i=tail;i>=;i--)
{
now=q[i];
siz[now]=;
int mxsiz=;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
siz[now]+=siz[ne->np];
if (siz[ne->np]>mxsiz)
{
mxsiz=siz[ne->np];
son[now]=ne->np;
}
}
}
}
int stack[MAXN],tops=-;
void dfs(int now)
{
Edge *ne;
memset(spos,0x3f,sizeof(spos));
memset(tpos,,sizeof(tpos));
stack[++tops]=now;
top[now]=now;
while (~tops)
{
now=stack[tops--];
pos[now]=++dfstime;
tpos[top[now]]=max(tpos[top[now]],pos[now]);
spos[top[now]]=min(spos[top[now]],pos[now]);
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now] || ne->np==son[now])continue;
stack[++tops]=ne->np;
top[ne->np]=ne->np;
}
if (son[now])
{
stack[++tops]=son[now];
top[son[now]]=top[now];
}
}
}
int troot[MAXN]; int main()
{
freopen("input.txt","r",stdin);
int n,m,x,y,z;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
a[i]=nextInt();
for (int i=;i<n;i++)
{
x=nextInt();y=nextInt();
//scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
bfs();
dfs();
for (int i=;i<=n;i++)
b[pos[i]]=a[i];
for (int i=;i<=n;i++)
{
if (top[i]==i)
Build_sgt(troot[i],spos[i],tpos[i]);
else
troot[i]=-;
}
int opt;
for (int i=;i<m;i++)
{
opt=nextInt();
//scanf("%d",&opt);
if (opt==)
{
x=nextInt();y=nextInt();z=nextInt();
//scanf("%d%d%d",&x,&y,&z);
while (true)
{
if (top[x]==top[y])
{
if (pos[x]>pos[y])swap(x,y);
Add_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x],pos[y],z);
while (true)
{
pair<qword,int> pr;
pr=Query_sgt_max(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x],pos[y]);
if (pr.first<=)break;
Modify_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pr.second,pr.first);
}
break;
}
if (depth[top[x]]<depth[top[y]])swap(x,y);
Add_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x],z);
while (true)
{
pair<qword,int> pr;
pr=Query_sgt_max(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x]);
if (pr.first<=)break;
Modify_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pr.second,pr.first);
}
x=pnt[top[x]];
}
}else
{
//scanf("%d%d",&x,&y);
x=nextInt();y=nextInt();
qword res=;
while (true)
{
if (top[x]==top[y])
{
if (pos[x]>pos[y])swap(x,y);
res+=Query_sgt_sum(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x],pos[y]);
break;
}
if (depth[top[x]]<depth[top[y]])swap(x,y);
res+=Query_sgt_sum(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x]);
x=pnt[top[x]];
}
printf("%lld\n",res);
}
}
}

bzoj 4127: Abs 树链剖分的更多相关文章

  1. BZOJ 4127: Abs (树链剖分 线段树求区间绝对值之和 带区间加法)

    题意 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d(d>=0) 2 u v 表示询问路径 (u,v) 上点权绝对值的和 分析 绝对值之和不好处理,那么我们开 ...

  2. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  3. 【BZOJ-4127】Abs 树链剖分 + 线段树 (有趣的姿势)

    4127: Abs Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 381  Solved: 132[Submit][Status][Discuss] ...

  4. BZOJ 3083 遥远的国度 树链剖分

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 797  Solved: 181[Submit][Status] Descrip ...

  5. BZOJ 2157: 旅游( 树链剖分 )

    树链剖分.. 样例太大了根本没法调...顺便把数据生成器放上来 -------------------------------------------------------------------- ...

  6. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  7. BZOJ 2157 旅行(树链剖分码农题)

    写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...

  8. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  9. 【bzoj4127】Abs 树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

随机推荐

  1. zTree默认选中指定节点并执行事件

    var treeObj = $.fn.zTree.getZTreeObj("treeDemo"); var node = treeObj.getNodeByParam(" ...

  2. 【二分答案+贪心】UVa 1335 - Beijing Guards

    Beijing was once surrounded by four rings of city walls: the Forbidden City Wall, the Imperial City ...

  3. JAXB - XML Schema Types, Defining an Enumeration

    If you want a data type that enumerates discrete values you should use a restriction of the schema t ...

  4. hyperlink

    在list中create column时,注意HyperlinkOrPicture这一选项,如果某一列为HyperLinkOrPicture,那么在后台就不要再加<a></a> ...

  5. Android res资源文件夹的知识积累

    Android的开发框架耦合性还是比较低的,逻辑和布局被原生分开了.在Eclipse一般代码写在src文件夹下,资源等写在res文件夹下. drawable文件夹:该文件夹有很多变种,主要是为了适配A ...

  6. powerdesigner 使用的几点问题

    一.powerdesigner 没有DataBase?: powerdesigner 只有在选择物理模型PDM的时候才会出现数据库菜单. 二.PowerDesigner版本控制功能? 1.首先介绍一下 ...

  7. 用PL0语言求Fibonacci数列前m个中偶数位的数

    程序说明:求Fibonacci数列前m个中偶数位的数: 这是编译原理作业,本打算写 求Fibonacci数列前m个数:写了半天,不会写,就放弃了: 程序代码如下: var n1,n2,m,i; pro ...

  8. PHP页面间参数传递的四种方法详解

    2016-04-16 定义page01.php和page02.php两个php文件,将page01中的内容想办法传递到page02,然后供我们继续使用.------------------------ ...

  9. 紧跟时代步伐,让我们拥抱MVC 3

    作为一个开发者,我们不希望技术很快的更新,这是因为我们还没有完全掌握原来技术的基础上,又要掌握新的技术,作为天天忙忙碌碌的程序员,我们不希望还要额外的时间来学习,尤其是当我们的年龄,逐渐的变大的时候, ...

  10. 3d旋转--transform-style: preserve-3d,translate3d(x,y,z),perspective()

    transform-style: preserve-3d,translate3d(x,y,z),perspective() 让其倾斜的核心:加perspective(600px)让其动的核心:rans ...