肯定是树链剖分+线段树,关键是怎么维护

绝对值和这个东西显然不能简单的合并标记

因为对于负数,加之后绝对值和是变小的

那我们考虑对负数和非负数数分别维护

下面的问题就是经过操作如果负数变成了正数怎么办

注意每次加的都是正数,这意味着这样的变化最多发生n次,

每个数发生这种变化,我们就用push到底即可,这样最多nlogn的

所以我们只要在维护一个区间最大负数即可

 const inf=;
type node=record
po,next:longint;
end;
link=record
s0,s1,mx:int64;
s:longint;
end; var tree:array[..*] of link;
lazy:array[..*] of int64;
e:array[..*] of node;
top,fa,a,b,c,d,p,s:array[..] of longint;
t,i,x,y,ch,z,len,n,m:longint; function max(a,b:int64):int64;
begin
if a>b then exit(a) else exit(b);
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure add(x,y:longint);
begin
inc(len);
e[len].po:=y;
e[len].next:=p[x];
p[x]:=len;
end; procedure dfs1(x:longint);
var i,y:longint;
begin
i:=p[x];
s[x]:=;
while i<> do
begin
y:=e[i].po;
if s[y]= then
begin
fa[y]:=x;
d[y]:=d[x]+;
dfs1(y);
s[x]:=s[x]+s[y];
end;
i:=e[i].next;
end;
end; procedure dfs2(x:longint);
var q,i,y:longint;
begin
inc(t);
c[x]:=t;
b[t]:=x;
i:=p[x];
q:=;
while i<> do
begin
y:=e[i].po;
if c[y]= then
if s[y]>s[q] then q:=y;
i:=e[i].next;
end;
if q<> then
begin
top[q]:=top[x];
dfs2(q);
end;
i:=p[x];
while i<> do
begin
y:=e[i].po;
if c[y]= then
begin
top[y]:=y;
dfs2(y);
end;
i:=e[i].next;
end;
end; procedure update(i:longint);
begin
tree[i].s0:=tree[i*].s0+tree[i*+].s0;
tree[i].s1:=tree[i*].s1+tree[i*+].s1;
tree[i].s:=tree[i*].s+tree[i*+].s;
tree[i].mx:=max(tree[i*].mx,tree[i*+].mx);
end; procedure build(i,l,r:longint);
var m:longint;
begin
if l=r then
begin
if a[b[l]]>= then
begin
tree[i].s0:=a[b[l]];
tree[i].s:=;
tree[i].mx:=-inf;
end
else begin
tree[i].s1:=a[b[l]];
tree[i].mx:=a[b[l]];
end;
end
else begin
m:=(l+r) shr ;
build(i*,l,m);
build(i*+,m+,r);
update(i);
end;
end; procedure modi(i,len:longint; z:int64);
begin
inc(lazy[i],z);
inc(tree[i].mx,z);
inc(tree[i].s0,int64(tree[i].s)*z);
inc(tree[i].s1,int64(len-tree[i].s)*z);
end; procedure push(i,l,r:longint);
var m:longint;
begin
m:=(l+r) shr ;
modi(i*,m-l+,lazy[i]);
modi(i*+,r-m,lazy[i]);
lazy[i]:=;
end; procedure down(i,l,r:longint);
var m:longint;
begin
if l=r then
begin
tree[i].s0:=tree[i].mx;
tree[i].s:=;
tree[i].mx:=-inf;
tree[i].s1:=;
end
else begin
m:=(l+r) shr ;
if lazy[i]<> then push(i,l,r);
if tree[i*].mx>= then down(i*,l,m);
if tree[i*+].mx>= then down(i*+,m+,r);
update(i);
end;
end; procedure ins(i,l,r,x,y:longint);
var m:longint;
begin
if (x<=l) and (y>=r) then
begin
if tree[i].mx+z>= then
begin
inc(lazy[i],z);
inc(tree[i].mx,z);
down(i,l,r);
end
else modi(i,r-l+,z);
end
else begin
if lazy[i]<> then push(i,l,r);
m:=(l+r) shr ;
if x<=m then ins(i*,l,m,x,y);
if y>m then ins(i*+,m+,r,x,y);
update(i);
end;
end; function get(i,l,r,x,y:longint):int64;
var m:longint;
s:int64; begin
if (x<=l) and (y>=r) then exit(tree[i].s0+abs(tree[i].s1))
else begin
if lazy[i]<> then push(i,l,r);
m:=(l+r) shr ;
s:=;
if x<=m then s:=s+get(i*,l,m,x,y);
if y>m then s:=s+get(i*+,m+,r,x,y);
exit(s);
end;
end; procedure work(x,y:longint);
var f1,f2:longint;
begin
f1:=top[x];
f2:=top[y];
while f1<>f2 do
begin
if d[f1]>=d[f2] then
begin
ins(,,n,c[f1],c[x]);
x:=fa[f1];
f1:=top[x];
end
else begin
ins(,,n,c[f2],c[y]);
y:=fa[f2];
f2:=top[y];
end;
end;
if c[x]>c[y] then swap(x,y);
ins(,,n,c[x],c[y]);
end; function ask(x,y:longint):int64;
var f1,f2:longint;
begin
ask:=;
f1:=top[x];
f2:=top[y];
while f1<>f2 do
begin
if d[f1]>=d[f2] then
begin
ask:=ask+get(,,n,c[f1],c[x]);
x:=fa[f1];
f1:=top[x];
end
else begin
ask:=ask+get(,,n,c[f2],c[y]);
y:=fa[f2];
f2:=top[y];
end;
end;
if c[x]>c[y] then swap(x,y);
ask:=ask+get(,,n,c[x],c[y]);
end; begin
readln(n,m);
for i:= to n do
read(a[i]);
for i:= to n- do
begin
readln(x,y);
add(x,y);
add(y,x);
end;
dfs1();
top[]:=;
dfs2();
build(,,n);
for i:= to m do
begin
read(ch,x,y);
if ch= then
begin
readln(z);
work(x,y);
end
else begin
readln;
writeln(ask(x,y));
end;
end;
end.

bzoj4127的更多相关文章

  1. [bzoj4127]Abs_树链剖分_线段树

    Abs bzoj-4127 题目大意:给定一棵数,支持链加和链上权值的绝对值的和. 注释:$1\le n,m \le 10^5$,$\delta \ge 0$,$|a_i|\le 10^8$. 想法: ...

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

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

  3. BZOJ4127: Abs

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

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

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

  5. bzoj4127 Abs 树链剖分+线段树+均摊分析

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4127 题解 首先区间绝对值和可以转化为 \(2\) 倍的区间正数和 \(-\) 区间和.于是问 ...

随机推荐

  1. MySql计数器,如网站点击数,如何实现高性能高并发的计数器功能

    MySql计数器,如网站点击数,如何实现高性能高并发的计数器功能 Clicks: Date: -- :: Power By 李轩Lane TagMysql计数器高性能 现在有很多的项目,对计数器的实现 ...

  2. 动态修改 NodeJS 程序中的变量值

    如果一个 NodeJS 进程正在运行,有办法修改程序中的变量值么?答案是:通过 V8 的 Debugger 接口可以!本文将详细介绍实现步骤. 启动一个 HTTP Server 用简单的 Hello ...

  3. Java异常类和自定义异常类

    自定义异常类: public class ExtendsException extends Exception { private static final long serialVersionUID ...

  4. 高质量图形库:pixellib

    点这里 pixellib 是高质量 2D 图形库: 高质量抗锯齿,矢量图形绘制 多种图像格式: RGB, BGR, ARGB, ABGR, RGBA, BGRA 8 / 15 / 16 / 24 / ...

  5. POJ 1507

    #include<iostream> #include<stdio.h> using namespace std; #include<iomanip> double ...

  6. Linux下搭建Android NDK , Linux 驱动开发环境

    Eclispe Luna(4.4):http://www.eclipse.org/downloads/ CDT :http://www.eclipse.org/cdt/downloads.php AD ...

  7. Android 注入详解

    Android下的注入的效果是类似于Windows下的dll注入,关于Windows下面的注入可以参考这篇文章Windows注入术.而Android一般处理器是arm架构,内核是基于linux,因此进 ...

  8. C#获取当前路径的方法

    C#获取当前路径的方法如下: 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName -获取模块的完整路径. 2. ...

  9. HDFS Protocol修改流程

        相对于1.x版本的Hadoop,2.x版本的Hadoop采用了Protocol Buffer作为序列化反序列化工具,以及RPC通讯工具.这样当我们对Hadoop源码进行修改之前,就需要了解Ha ...

  10. QStandardItemModel简单好用,QTableView带进度条

    类QabstractItemModel,QabstractListModel,QAbstractTableModel不保存数据,用户需要从这些类派生出子类,并在子类中定义某种数据结构来保存数据.与此不 ...