这个题感觉很厉害的样子。。

首先我们注意到一点:每次加的 $d$ 都是非负的。

那么就说明一个数只可能从负数变成非负数并且只会变一次。

所以我们就可以暴力地去改变一个数的正负情况。

然后我们就可以用树链剖分,维护一下区间的最大负数和负数的个数就可以了。

时间复杂度 $O(n\log^2 n)$,空间复杂度 $O(n)$。

 #include <cstdio>
typedef long long LL;
#define N 262144 + 5
#define INF 1234567890987654321LL int n, m, tot, cnt, A[N], Head[N], Root[N], Fa[N], Ad[N], Pos[N], Num[N], Dfn[N], Len[N], Size[N], Son[N], q[N]; struct Edge
{
int next, node;
}E[N]; struct Segment_Tree
{
int l, r, neg_cnt;
LL sum, delta, neg_Max;
}h[N]; inline void addedge(int u, int v)
{
E[++ tot].next = Head[u], Head[u] = tot;
E[tot].node = v;
E[++ tot].next = Head[v], Head[v] = tot;
E[tot].node = u;
} inline LL Abs(LL x)
{
return x > ? x : -x;
} inline void dfs(int z)
{
Size[z] = ;
for (int i = Head[z]; i; i = E[i].next)
{
int d = E[i].node;
if (d == Fa[z]) continue ;
Fa[d] = z;
dfs(d);
Size[z] += Size[d];
}
for (int i = Head[z]; i; i = E[i].next)
{
int d = E[i].node;
if (d == Fa[z]) continue ;
if (!Son[z] || Size[d] > Size[Son[z]])
Son[z] = d;
}
} inline void update(int x)
{
h[x].sum = h[h[x].l].sum + h[h[x].r].sum;
h[x].neg_Max = h[h[x].l].neg_Max > h[h[x].r].neg_Max ? h[h[x].l].neg_Max : h[h[x].r].neg_Max;
h[x].neg_cnt = h[h[x].l].neg_cnt + h[h[x].r].neg_cnt;
} inline void Build(int &x, int l, int r)
{
if (!x) x = ++ tot;
if (l == r)
{
h[x].sum = Abs(A[q[l]]);
if (A[q[l]] < ) h[x].neg_Max = A[q[l]], h[x].neg_cnt = ;
else h[x].neg_Max = -INF;
return ;
}
int mid = l + r >> ;
Build(h[x].l, l, mid);
Build(h[x].r, mid + , r);
update(x);
} inline void apply(int x, int l, int r, LL d)
{
h[x].sum += d * (r - l + - h[x].neg_cnt * );
h[x].delta += d;
h[x].neg_Max += d;
} inline void push(int x, int l, int r)
{
if (h[x].delta)
{
int mid = l + r >> ;
apply(h[x].l, l, mid, h[x].delta);
apply(h[x].r, mid + , r, h[x].delta);
h[x].delta = ;
}
} inline void Point_Modify(int x, int l, int r, LL d)
{
if (l == r)
{
h[x].sum = -h[x].sum;
h[x].neg_Max = -INF;
h[x].neg_cnt = ;
return ;
}
int mid = l + r >> ;
push(x, l, r);
if (h[h[x].l].neg_Max > h[h[x].r].neg_Max)
Point_Modify(h[x].l, l, mid, d);
else Point_Modify(h[x].r, mid + , r, d);
update(x);
} inline void Modify(int x, int l, int r, int s, int t, LL d)
{
if (l == s && r == t)
{
while (h[x].neg_Max >= -d)
Point_Modify(x, l, r, d);
apply(x, l, r, d);
return ;
}
push(x, l, r);
int mid = l + r >> ;
if (t <= mid) Modify(h[x].l, l, mid, s, t, d);
else if (s > mid) Modify(h[x].r, mid + , r, s, t, d);
else Modify(h[x].l, l, mid, s, mid, d), Modify(h[x].r, mid + , r, mid + , t, d);
update(x);
} inline LL Query(int x, int l, int r, int s, int t)
{
if (l == s && r == t) return h[x].sum;
push(x, l, r);
int mid = l + r >> ;
if (t <= mid) return Query(h[x].l, l, mid, s, t);
else if (s > mid) return Query(h[x].r, mid + , r, s, t);
else return Query(h[x].l, l, mid, s, mid) + Query(h[x].r, mid + , r, mid + , t);
} inline void Prepare()
{
tot = ;
for (int i = ; i <= n; i ++)
{
if (Ad[i]) continue ;
Dfn[i] = Dfn[Fa[i]] + ;
q[] = ;
cnt ++;
for (int x = i; x; x = Son[x])
{
Ad[x] = i, Pos[x] = ++ Len[cnt];
Num[x] = cnt, Dfn[x] = Dfn[i];
q[++ q[]] = x;
}
Build(Root[cnt], , Len[cnt]);
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("4127.in", "r", stdin);
freopen("4127.out", "w", stdout);
#endif scanf("%d%d", &n, &m);
for (int i = ; i <= n; i ++)
scanf("%d", A + i);
for (int i = , u, v; i < n; i ++)
{
scanf("%d%d", &u, &v);
addedge(u, v);
}
dfs();
Prepare();
for (int op, u, v; m; m --)
{
scanf("%d", &op);
if (op == )
{
LL d;
scanf("%d%d%lld", &u, &v, &d);
if (Dfn[u] < Dfn[v]) u = u - v, v = u + v, u = v - u;
for (; Dfn[u] > Dfn[v]; u = Fa[Ad[u]])
Modify(Root[Num[u]], , Len[Num[u]], , Pos[u], d);
for (; Ad[u] != Ad[v]; u = Fa[Ad[u]], v = Fa[Ad[v]])
{
Modify(Root[Num[u]], , Len[Num[u]], , Pos[u], d);
Modify(Root[Num[v]], , Len[Num[v]], , Pos[v], d);
}
if (Pos[u] > Pos[v]) u = u - v, v = u + v, u = v - u;
Modify(Root[Num[u]], , Len[Num[u]], Pos[u], Pos[v], d);
}
else
{
scanf("%d%d", &u, &v);
LL ans = ;
if (Dfn[u] < Dfn[v]) u = u - v, v = u + v, u = v - u;
for (; Dfn[u] > Dfn[v]; u = Fa[Ad[u]])
ans += Query(Root[Num[u]], , Len[Num[u]], , Pos[u]);
for (; Ad[u] != Ad[v]; u = Fa[Ad[u]], v = Fa[Ad[v]])
{
ans += Query(Root[Num[u]], , Len[Num[u]], , Pos[u]);
ans += Query(Root[Num[v]], , Len[Num[v]], , Pos[v]);
}
if (Pos[u] > Pos[v]) u = u - v, v = u + v, u = v - u;
ans += Query(Root[Num[u]], , Len[Num[u]], Pos[u], Pos[v]);
printf("%lld\n", ans);
}
} #ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return ;
}

4127_Gromah

BZOJ 4127 Abs 解题报告的更多相关文章

  1. bzoj 4127: Abs 树链剖分

    4127: Abs Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 11  Solved: 5[Submit][Status][Discuss] Des ...

  2. BZOJ[4127] Abs

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=4127 不算难的样子,才见过此类模型. 首先可以发现每次修改只增不减,那么这$O(n)$的负数最 ...

  3. BZOJ 2959: 长跑 解题报告

    2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...

  4. BZOJ 4238 电压 解题报告

    BZOJ 4238 电压 考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环 则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上. 考虑建出dfs树,那么返祖边一定 ...

  5. BZOJ 3159: 决战 解题报告

    BZOJ 3159: 决战 1 sec 512MB 题意: 给你一颗\(n\)个点,初始点权为\(0\)的有跟树,要求支持 Increase x y w 将路径\(x\)到\(y\)所有点点权加上\( ...

  6. BZOJ 3328: PYXFIB 解题报告

    BZOJ 3328: PYXFIB 题意 给定\(n,p,k(1\le n\le 10^{18},1\le k\le 20000,1\le p\le 10^9,p \ is \ prime,k|(p- ...

  7. BZOJ 4302 Buildings 解题报告

    这个题好像很有趣的样子. 题目分析: 房间都是 $1\times k$ 的,也就是一条一条的.这个好像比较显然的样子. 一个房间如果要覆盖某个格子$u$,那么这个房间的面积至少为 $dis(u, Bo ...

  8. BZOJ 3160 万径人踪灭 解题报告

    这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...

  9. BZOJ 3953 Self-Assembly 解题报告

    首先,我们可以先考虑一个暴力一点的算法: 对于任意两个分子,如果它们能以至少一种进行匹配,那么我们就在这两个分子之间连一条边. 然后如果我们能找到一个环,就说明是 unbounded,否则就是 bou ...

随机推荐

  1. HttpClient(4.3.5) - HttpClient Proxy Configuration

    Even though HttpClient is aware of complex routing scemes and proxy chaining, it supports only simpl ...

  2. UpdatePanel中执行js

    在UpdatePanel中,直接使用Page.ClientScript.RegisterStartupScript的方式执行javascript,会导致无法执行.原因可能是因为RegisterStar ...

  3. 和阿文一起学H5-文字云制作

    ---恢复内容开始--- 实用工具!优秀的标签云免费生成工具 来源:http://www.uisdc.com/online-word-cloud-generators 标签云或文字云是关键词的视觉化描 ...

  4. 转:SqlServer2008误操作数据(delete或者update)后恢复数据

    Sqlserver2008误操作数据(delete或者update)后恢复数据(转) 实际工作中,有时会直接在数据库中操作数据,比如对数据进行delete或者update操作,当进行这些操作的时候,如 ...

  5. Android之帧动画

    MySurfaceView类: package com.fm; import android.content.Context; import android.graphics.Bitmap; impo ...

  6. TCP/IP——内外网IP+子网掩码作用+PING(网络总结)

    目录: 1.如何区分内网IP和外网IP? 保留字段 2.子网掩码是起什么作用的? 将DNS和IP异或,表示哪段起作用 3.ping到底起什么作用? ping本地.ping远程 下面针对上面三个问题分别 ...

  7. iMAC——全新重装Mac系统

    在参考网上重装Mac系统教程的时候,感觉这篇教程挺不错: http://www.iplaysoft.com/osx-yosemite-usb-install-drive.html (此教程终端命令处需 ...

  8. 日常bug及解决方法记录

    工作中经常会遇到一些Bug,时间长了有时候就忘记了,这样不好. 特地在这加一个随笔,把以后出现的有价值一点的bug记录在这里,提醒自己,也可以给刚入门的同学一些参考,避免这些坑. 1:界面已经销毁,代 ...

  9. JS 截取字符串函数

    一.函数:split() 功能:使用一个指定的分隔符把一个字符串分割存储到数组 例子: str=”jpg|bmp|gif|ico|png”; arr=theString.split(”|”); //a ...

  10. OC7_目录操作

    // // main.m // OC7_目录操作 // // Created by zhangxueming on 15/6/19. // Copyright (c) 2015年 zhangxuemi ...