Abs bzoj-4127

题目大意:给定一棵数,支持链加和链上权值的绝对值的和。

注释:$1\le n,m \le 10^5$,$\delta \ge 0$,$|a_i|\le 10^8$。

想法:看完题,以为又是什么数据结构裸题。然后发现绝对值... ...卧槽?啥jb玩意儿?绝对值?这怎么加?开始的想法是维护一个do标记,表示这个区间有没有负值,如果没有直接懒标记,如果有,往下走的时候负数取出来,然后二分治... ...不想写,上网查的题解。我们先树链剖分之后建线段树。紧接着我们对于一段区间维护一个小信息:maxdown。表示这个点所代表的区间中的所有负值中的最大值的绝对值。我们发现所有的增量都是正的,所以每一个数的正负号只能变动一次并且只能从负号变成正号。所以在区间修改的时候如果这个区间有负值我们就暴力修改即可。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
#define lson l,mid,x<<1
#define rson mid+1,r,x<<1|1
using namespace std;
typedef long long ll;
const int inf=1<<30;
int a[N],head[N],to[N<<1],next[N<<1],cnt,fa[N],deep[N],sv[N],bl[N],pos[N],tot,v[N];
int n,val[N<<2],si[N<<2],add[N<<2];
ll sum[N<<2];
void addedge(int x,int y)
{
to[++cnt]=y,next[cnt]=head[x],head[x]=cnt;
}
void dfs1(int x)
{
sv[x]=1;
for(int i=head[x];i;i=next[i])
if(to[i]!=fa[x])
fa[to[i]]=x,deep[to[i]]=deep[x]+1,dfs1(to[i]),sv[x]+=sv[to[i]];
}
void dfs2(int x,int c)
{
int k=0;
bl[x]=c,pos[x]=++tot,v[tot]=a[x];
for(int i=head[x];i;i=next[i])
if(to[i]!=fa[x]&&sv[to[i]]>sv[k])
k=to[i];
if(k)
{
dfs2(k,c);
for(int i=head[x];i;i=next[i])
if(to[i]!=fa[x]&&to[i]!=k)
dfs2(to[i],to[i]);
}
}
void pushup(int x)
{
int l=x<<1,r=x<<1|1;
sum[x]=sum[l]+sum[r];
if(val[l]>0&&val[r]>0)val[x]=min(val[l],val[r]);
else if(val[l]>0)val[x]=val[l];
else if(val[r]>0)val[x]=val[r];
else val[x]=0;
si[x]=si[l]+si[r];
}
void pushdown(int x)
{
if(add[x])
{
int l=x<<1,r=x<<1|1;
sum[l]+=(ll)si[l]*add[x],val[l]-=add[x],add[l]+=add[x];
sum[r]+=(ll)si[r]*add[x],val[r]-=add[x],add[r]+=add[x];
add[x]=0;
}
}
void build(int l,int r,int x)
{
if(l==r)
{
if(v[l]<0) sum[x]=val[x]=-v[l],si[x]=-1;
else sum[x]=v[l],val[x]=0,si[x]=1;
return;
}
int mid=(l+r)>>1;
build(lson),build(rson);
pushup(x);
}
void update(int b,int e,int a,int l,int r,int x)
{
if(b<=l&&r<=e&&(val[x]<=0||val[x]>a)) sum[x]+=(ll)si[x]*a,val[x]-=a,add[x]+=a;
else if(l==r) sum[x]=a-sum[x],val[x]=0,si[x]=1;
else
{
pushdown(x);
int mid=(l+r)>>1;
if(b<=mid) update(b,e,a,lson);
if(e>mid) update(b,e,a,rson);
pushup(x);
}
}
ll query(int b,int e,int l,int r,int x)
{
if(b<=l&&r<=e)return sum[x];
pushdown(x);
int mid=(l+r)>>1;
ll ans=0;
if(b<=mid)ans+=query(b,e,lson);
if(e>mid)ans+=query(b,e,rson);
return ans;
}
void modify(int x,int y,int z)
{
while(bl[x]!=bl[y])
{
if(deep[bl[x]]<deep[bl[y]])swap(x,y);
update(pos[bl[x]],pos[x],z,1,n,1),x=fa[bl[x]];
}
if(deep[x]>deep[y])swap(x,y);
update(pos[x],pos[y],z,1,n,1);
}
ll solve(int x,int y)
{
ll ans=0;
while(bl[x]!=bl[y])
{
if(deep[bl[x]]<deep[bl[y]])swap(x,y);
ans+=query(pos[bl[x]],pos[x],1,n,1),x=fa[bl[x]];
}
if(deep[x]>deep[y])swap(x,y);
ans+=query(pos[x],pos[y],1,n,1);
return ans;
}
int main()
{
int m,opt,x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<n;i++)scanf("%d%d",&x,&y),addedge(x,y),addedge(y,x);
dfs1(1),dfs2(1,1),build(1,n,1);
while(m--)
{
scanf("%d%d%d",&opt,&x,&y);
if(opt==1)scanf("%d",&z),modify(x,y,z);
else printf("%lld\n",solve(x,y));
}
return 0;
}

小结:注意题目中的数据范围,对于一些比较特殊的性质要发掘并利用。

[bzoj4127]Abs_树链剖分_线段树的更多相关文章

  1. [bzoj4196][Noi2015]软件包管理器_树链剖分_线段树

    软件包管理器 bzoj-4196 Noi-2015 题目大意:Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件 ...

  2. [bzoj3694]最短路_树链剖分_线段树

    最短路 bzoj-3694 题目大意:给你一个n个点m条边的无向图,源点为1,并且以点1为根给出最短路树.求对于2到n的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径上的最后一条边. 注 ...

  3. bzoj 3730: 震波 动态点分治_树链剖分_线段树

    ##### 题目描述 : 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着 ...

  4. bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树

    [Submit][Status][Discuss] Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳 ...

  5. [NOI2015]软件包管理器 树链剖分_线段树

    没有太大难度,刷水有益健康 Code: // luogu-judger-enable-o2 #include <bits/stdc++.h> #define setIO(s) freope ...

  6. 洛谷 P2542 [AHOI2005]航线规划 树链剖分_线段树_时光倒流_离线

    Code: #include <map> #include <cstdio> #include <algorithm> #include <cstring&g ...

  7. poj 3237 Tree(树链剖分,线段树)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description ...

  8. bzoj 4034 [HAOI2015] T2(树链剖分,线段树)

    4034: [HAOI2015]T2 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1536  Solved: 508[Submit][Status] ...

  9. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

随机推荐

  1. Gym - 101981G The 2018 ICPC Asia Nanjing Regional Contest G.Pyramid 找规律

    题面 题意:数一个n阶三角形中,有多少个全等三角形,n<=1e9 题解:拿到题想找规律,手画开始一直数漏....,最后还是打了个表 (打表就是随便定个点为(0,0),然后(2,0),(4,0), ...

  2. html5的Form新特性

    form新增的输入型控件: 名称 说明 图例 email 电子邮箱文本框,显示跟普通的没什么区别 tel  电话号码,pc端不会有明显的变化,但是移动端会自动切换键盘,输入有误不会阻止默认提交   u ...

  3. mybatis parameterType报错:There is no getter for property named 'xxx' in 'class java.lang.String'

    方法1: 当parameterType = "java.lang.String" 的时候,参数读取的时候必须为 _parameter 方法2: 在dao层的时候,设置一下参数,此方 ...

  4. Kali linux 2016.2(Rolling)之 Nessus安装及Plugins Download Fail 解决方法

    最近,因科研需要,学习Nessus. Nessus是一款优秀的漏洞扫描软件,在其v6 HOME版本中在线更新漏洞插件不成功,采用离线更新,成功地更新了插件,在此将更新方法进行分享. 1.Nessus软 ...

  5. RabbitMQ 官方NET教程(六)【RPC】

    在第二个教程中,我们学习了如何使用Work Queues在多个工作者之间分配耗时的任务. 但是如果我们需要在远程计算机上运行功能并等待结果怎么办? 那是一个不同的模式. 此模式通常称为远程过程调用或R ...

  6. EasyUI 编写实体类树状选择器

    <%@ page contentType="text/html;charset=UTF-8"%> <%@ include file="/WEB-INF/ ...

  7. 联想笋尖S90(S90-t 、S90-u)解锁BootLoader

    工具下载链接: http://pan.baidu.com/s/1eSgZuka 备用下载链接: http://pan.baidu.com/s/1dFKqSId 本篇教程,仅限于联想笋尖S90(S90- ...

  8. 24 javascript best practices for beginner(only 23 finally)

    原文是英文,链接: http://net.tutsplus.com/tutorials/JavaScript-ajax/24-JavaScript-best-practices-for-beginne ...

  9. 调试程序时找不到DLL的解决办法

    最近调试程序的经常弹出找不到DLL.只好一个个把DLL拷贝到程序目录下(我是拷贝到源文件目录,也有人说是Debug目录). 其实可以这么设置: 项目属性->配置属性->调试->工作目 ...

  10. iproute2和tc的高级路由用法

    #Linux advanced router ip link show #显示链路 ip addr show #显示地址(或ifconfig) ip route show #显示路由(route -n ...