因为d>=0,所以一个位置的数只会单调不降并且只会有一次穿过0.

用这个性质,我们我可在线段树中记录正数负数的个数和和,以及最大的负数以及答案.

修改操作:如果当前最大负数+d<=0,那么就直接加到懒惰标记中,否则就暴力向下传递.

因为每个节点最多被额外访问该区间负数个数次,所以所有点总共会被额外访问O(nlogn)次,在加上修改操作和询问操作的普通访问O(mlogn)次,所以时间复杂度是有保证的.

谢谢mhy12345的讲解.

 /**************************************************************
Problem: 4127
User: idy002
Language: C++
Result: Accepted
Time:7872 ms
Memory:49256 kb
****************************************************************/ #include <cstdio>
#include <vector>
#include <algorithm>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)<0?-(a):(a))
#define oo 0x3f3f3f3f3f3f3f3fLL
#define N 200010
//#define fprintf(...)
using namespace std; typedef long long dnt; void getn( int &v ) {
char ch=getchar();
bool neg = false;
while( ch!='-' && (ch<'' || ch>'') ) ch=getchar();
if( ch=='-' ) {
neg = true;
ch = getchar();
}
v = ch-'';
ch = getchar();
while( ''<=ch && ch<='' ) {
v = v*+ch-'';
ch = getchar();
}
if( neg ) v=-v;
} struct Node {
dnt ans, sum[], cnt[], nmx, tag;
Node *ls, *rs;
inline void init( int v ) {
if( v< ) {
sum[] = v;
cnt[] = ;
sum[] = ;
cnt[] = ;
ans = -v;
tag = ;
nmx = v;
} else {
sum[] = ;
cnt[] = ;
sum[] = v;
cnt[] = ;
tag = ;
ans = v;
nmx = -oo;
}
}
inline void update() {
sum[] = ls->sum[] + rs->sum[];
sum[] = ls->sum[] + rs->sum[];
cnt[] = ls->cnt[] + rs->cnt[];
cnt[] = ls->cnt[] + rs->cnt[];
ans = ls->ans + rs->ans;
nmx = max( ls->nmx, rs->nmx );
}
inline void pushdown() {
if( tag ) {
ls->nmx += tag;
rs->nmx += tag;
ls->sum[] += ls->cnt[]*tag;
ls->sum[] += ls->cnt[]*tag;
rs->sum[] += rs->cnt[]*tag;
rs->sum[] += rs->cnt[]*tag;
ls->ans = ls->sum[]-ls->sum[];
rs->ans = rs->sum[]-rs->sum[];
ls->tag += tag;
rs->tag += tag;
tag = ;
}
}
void modify( int lf, int rg, int L, int R, int delta ) {
if( lf==rg ) {
if( cnt[] ) {
if( sum[]+delta<= ) {
sum[]+=delta;
nmx = sum[];
ans = -sum[];
} else {
sum[] = sum[]+delta;
ans = sum[];
cnt[] = ;
sum[] = cnt[] = ;
nmx = -oo;
}
} else {
sum[]+=delta;
ans = sum[];
}
return;
}
if( L<=lf && rg<=R && nmx+delta<= ) {
nmx += delta;
sum[] += cnt[]*delta;
sum[] += cnt[]*delta;
ans = sum[]-sum[];
tag += delta;
return;
}
pushdown();
int mid=(lf+rg)>>;
if( L<=mid ) ls->modify(lf,mid,L,R,delta);
if( R>mid ) rs->modify(mid+,rg,L,R,delta);
update();
}
dnt query( int lf, int rg, int L, int R ) {
if( L<=lf && rg<=R ) return ans;
pushdown();
int mid=(lf+rg)>>;
dnt rt = ;
if( L<=mid ) rt+=ls->query(lf,mid,L,R);
if( R>mid ) rt+=rs->query(mid+,rg,L,R);
update();
return rt;
}
}pool[N*], *tail=pool, *root; int n, m;
int aa[N], bb[N];
int head[N], dest[N<<], next[N<<], etot;
int fat[N], siz[N], son[N], top[N], dep[N], vid[N], qu[N], bg, ed; void adde( int u, int v ) {
etot++;
dest[etot] = v;
next[etot] = head[u];
head[u] = etot;
}
Node *build( int lf, int rg ) {
Node *nd = ++tail;
if( lf==rg) {
nd->init(bb[lf]);
return nd;
}
int mid=(lf+rg)>>;
nd->ls = build( lf, mid );
nd->rs = build( mid+, rg );
nd->update();
return nd;
}
void build_dcp( int s ) {
// fat dep
fat[s] = ;
dep[s] = ;
qu[bg=ed=] = s;
while( bg<=ed ) {
int u=qu[bg++];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==fat[u] ) continue;
fat[v] = u;
dep[v] = dep[u]+;
qu[++ed] = v;
}
}
// siz son
for( int i=ed; i>=; i-- ) {
int u=qu[i], p=fat[u];
siz[u]++;
if( p ) {
siz[p] += siz[u];
if( siz[son[p]]<siz[u] ) son[p]=u;
}
}
// vid top
vid[s] = ;
top[s] = s;
for( int i=; i<=ed; i++ ) {
int u=qu[i];
int cur=vid[u]+;
if( son[u] ) {
vid[son[u]] = cur;
top[son[u]] = top[u];
cur += siz[son[u]];
}
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==fat[u] || v==son[u] ) continue;
vid[v] = cur;
top[v] = v;
cur += siz[v];
}
}
// segment tree
for( int i=; i<=n; i++ )
bb[vid[i]] = aa[i];
// for( int i=1; i<=n; i++ )
// fprintf( stderr, "%d ", bb[i] );
// fprintf( stderr, "\n" );
root = build( , n );
}
void modify( int u, int v, int delta ) {
while( top[u]!=top[v] ) {
if( dep[top[u]]<dep[top[v]] ) swap(u,v);
root->modify(,n,vid[top[u]],vid[u],delta);
// fprintf( stderr, "modify( %d %d %d )\n", vid[top[u]], vid[u], delta );
u=fat[top[u]];
}
if( dep[u]<dep[v] ) swap(u,v);
root->modify(,n,vid[v],vid[u],delta);
// fprintf( stderr, "modify( %d %d %d )\n", vid[v], vid[u], delta );
}
dnt query( int u, int v ) {
dnt rt = ;
while( top[u]!=top[v] ) {
if( dep[top[u]]<dep[top[v]] ) swap(u,v);
rt += root->query(,n,vid[top[u]],vid[u]);
// fprintf( stderr, "query( %d %d ) rt = %lld\n", vid[top[u]], vid[u], rt );
u=fat[top[u]];
}
if( dep[u]<dep[v] ) swap(u,v);
rt += root->query(,n,vid[v],vid[u]);
// fprintf( stderr, "query( %d %d ) rt = %lld\n", vid[v], vid[u], rt );
return rt;
}
int main() {
getn(n); getn(m);
for( int i=; i<=n; i++ )
getn(aa[i]);
for( int i=,u,v; i<n; i++ ) {
getn(u); getn(v);
adde( u, v );
adde( v, u );
}
build_dcp();
for( int t=,opt,u,v,d; t<=m; t++ ) {
getn(opt);
if( opt== ) {
getn(u);getn(v);getn(d);
modify( u, v, d );
} else {
getn(u); getn(v);
printf( "%lld\n", query(u,v) );
}
}
}

bzoj 4127 线段树维护绝对值之和的更多相关文章

  1. bzoj 1018 线段树维护连通性

    本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护. 对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边 ...

  2. BZOJ 1018 线段树维护图的连通性问题

    思路: 我们可以搞一棵线段树 对于一段区间有6种情况需要讨论 左上右下.左上右上.左下右下.左下右上 这四种比较好维护 用左上右下举个例子吧 就是左儿子的左上右下&左区间到右区间下面有路&am ...

  3. BZOJ 2124 线段树维护hash值

    思路: http://blog.csdn.net/wzq_QwQ/article/details/47152909 (代码也是抄的他的) 自己写得垃圾线段树怎么都过不了 隔了两个月 再写 再挂 又隔了 ...

  4. BZOJ 1018 线段树维护图连通性

    用8个bool维护即可分别为LURU,LURD,LDRU,LDRD,LULD,RURD,Side[1],Side[2]即可. Side表示这一块有没有接到右边.Merge一下就可以了.码农题,WA了一 ...

  5. [BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】

    题目链接:BZOJ - 3995 题目分析 这道题..是我悲伤的回忆.. 线段树维护连通性,与 BZOJ-1018 类似,然而我省选之前并没有做过  1018,即使它在 ProblemSet 的第一页 ...

  6. [BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】

    题目链接:BZOJ - 1018 题目分析 这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题.. 这道题是线段树维护联通性的经 ...

  7. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  8. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  9. bzoj 4184: shallot (线段树维护线性基)

    题面 \(solution:\) 这一题绝对算的上是一道经典的例题,它向我们诠释了一种新的线段树维护方式(神犇可以跳过了).像这一类需要加入又需要维护删除的问题,我们曾经是遇到过的像莫对,线段树... ...

随机推荐

  1. Indepence Mode 备份 weblogic

    一般不在administation server 停止这个模式 管理服务器挂了,不会影响其他服务器的运行 备份一个domain copy  一个  /bin  把启动的脚本做一个修改  里面的doma ...

  2. Python标准库笔记(8) — pprint模块

    struct模块提供了用于在字节字符串和Python原生数据类型之间转换函数,比如数字和字符串. Python版本: 2.x & 3.x 该模块作用是完成Python数值和C语言结构体的Pyt ...

  3. Linux下如何在进程中获取虚拟地址对应的物理地址【转】

    转自:http://blog.csdn.net/kongkongkkk/article/details/74366200 如果让你编写一个程序,来获取虚拟地址对应的物理地址..你会试着操作MMU吗.. ...

  4. innobackupex 相关语法讲解【转】

    innobackupex 相关语法讲解 连接服务器 The database user used to connect to the server and its password are speci ...

  5. ARC073E Ball Coloring

    Problem AtCoder Solution 把点映射至二维平面,问题就变成了给定 \(n\) 个点,可以把点对 \(y=x\) 对称,求覆盖所有点的最小矩形面积. 可以先把所有点放到 \(y=x ...

  6. 007_苹果Mac系统锁屏不待机效果设置方法介绍

    Mac如何设置锁屏不断网?Mac如何设置锁屏不待机?这是一个非常麻烦的设置,有时候一锁屏幕电脑就跟着待机了,这非常的麻烦,所以今天小编就用图文教程的方式教大家Mac如何设置锁屏不断网Mac如何设置锁屏 ...

  7. shell用户管理->

    用户的添加与删除练习 -> 脚本1(if then) 思路:1.条件测试, 脚本使用案例, 创建用户[交互式创建] 1.怎么交互式 read -p 2.接收到对应字符串怎么创建用户 userad ...

  8. Ubuntu 搭建docker registry 私有仓库

    一.为什么要搭建 docker 私有仓库 原因有几个: 项目需要,不希望将项目放到 docker hub 上. 环境需求,考虑网络.效率的问题,希望在私有服务器上建立自用的仓库,提高便利性和访问速度. ...

  9. Tensorflow之训练MNIST(1)

    先说我遇到的一个坑,在下载MNIST训练数据的时候,代码报错: urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FA ...

  10. CVE-2014-1776 秘狐

    传说中的IE秘狐 [CNNVD]Microsoft Internet Explorer 释放后重用漏洞(CNNVD-201404-530) Microsoft Internet Explorer(IE ...