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

首先我们注意到一点:每次加的 $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. sqoop-1.4.6安装配置

    1. 下载sqoop-1.4.6并解压 wget http://archive.apache.org/dist/sqoop/1.4.6/sqoop-1.4.6.bin__hadoop-2.0.4-al ...

  2. unity3d游戏无法部署到windows phone8手机上的解决方法

    今天搞了个unity3d游戏,准备部署到自己的lumia 920上,数据线连接正常,操作正常,但是“build”以后,始终无法部署到手机上,也没有在选择的目录下生产任何相关文件.(你的系统必须是win ...

  3. 省市数据递归加载到TreeView

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  4. SQL 的一个技巧

    遇到一个需求,项目是我接手二次开发的,之前的大神设计数据库,订单表中没有订单号,现在让我加上这个号,规则是订单创建日期加上自增的ID,ID需要补足5位,例:00002,00124,01245这样.这个 ...

  5. Spring使用总结

    一.基础JAR包 spring-beans.jar spring-context.jar spring-core.jar spring-expression.jar 二.XML的配置 1.一级结构 & ...

  6. What are Upgrade, Product and Package Codes used for? By pusu

    Following content is reprinted from here, please go to the original website for more information. Au ...

  7. Windows系统 环境变量

    用户变量与系统变量 用户变量只对当前用户有效,而系统变量对所有用户有效.在检索命令时,系统变量会排在用户变量的前面.也就是说,如果两个地方都包含同一个命令,则优先执行系统变量指示路径下的命令. set ...

  8. Contiki系统介绍

    本文内容来源为contiki英文介绍,自己为了学习,将其大致翻译成中文,以便了解. 欢迎转载,转载请注明来源,如果有什么翻译不合适的地方,请留言指出,相互交流学习. 介绍 Contiki是一个开放源码 ...

  9. 提升程序的特权(AdjustTokenPrivileges)

    首先列出需要的函数 1.OpenProcessToken 2.AdjustTokenPrivileges 3. LookupPrivilegeValue ----------------------- ...

  10. ACE_linux:TCP通信

    1.涉及类 ACE_INET_Addr//ACE网络地址ACE_SOCK_Acceptor//ACE网络服务器ACE_SOCK_Connector//ACE网络客户端ACE_SOCK_Stream// ...