bzoj 4127: Abs 树链剖分
4127: Abs
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 11 Solved: 5
[Submit][Status][Discuss]
Description
给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和
Input
接下来一行n个整数a_i,表示点i的权值 接下来n-1行,每行两个整数u,v表示存在一条(u,v)的边 接下来m行,每行一个操作,输入格式见题目描述
Output
Sample Input
-4 1 5 -2
1 2
2 3
3 4
2 1 3
1 1 4 3
2 1 3
2 3 4
Sample Output
13
9
HINT
对于100%的数据,n,m <= 10^5 且 0<= d,|a_i|<= 10^8
我们分开处理正数负数情况,注意加数为正,所以一个负数被加成正数最多发生O(n)次,我们需要实现的就是快速的判定是否有某个负数加成了正数,维护负数集合中的最大值和位置即可。如果负数集合的最大值大于0,那么我们求得最大值所在位置,然后暴力将它修改到正数集合即可。
注意这道题INF取0x3f3f3f3f要出事。
第一次写链剖的每个链单独建线段树版本,不是太难。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 210000
#define MAXT MAXN*4
#define MAXV MAXN
#define MAXE MAXN*2
#define INFL 0x3f3f3f3f3f3f3f3f
#define smid ((l+r)>>1)
#define abs(x) ((x)>0?x:-(x))
typedef long long qword;
inline int nextInt()
{
register char ch;
register int x=;
register bool f=false;
while (ch=getchar(),ch<'' || ch>'')f|=ch=='-';
while (x=x*+ch-'',ch=getchar(),ch<='' && ch>='');
return x*(f?-:);
}
struct sgt_node
{
int lc,rc;
int sd;
qword sv;
qword pls;
pair<qword,int> mx;
}sgt[MAXT];
int topt=;
int a[MAXN];
int b[MAXN];
void update(int now)
{
sgt[now].mx=max(sgt[sgt[now].lc].mx,sgt[sgt[now].rc].mx);
sgt[now].sd=sgt[sgt[now].lc].sd+sgt[sgt[now].rc].sd;
sgt[now].sv=sgt[sgt[now].lc].sv+sgt[sgt[now].rc].sv;
}
void make_plus(int now,int l,int r,qword delta)
{
sgt[now].sv+=(qword)sgt[now].sd*delta;
sgt[now].pls+=delta;
sgt[now].mx.first+=delta;
}
void down(int now,int l,int r)
{
if (sgt[now].pls)
{
make_plus(sgt[now].lc,l,smid,sgt[now].pls);
make_plus(sgt[now].rc,smid+,r,sgt[now].pls);
sgt[now].pls=;
}
}
void Build_sgt(int &now,int l,int r)
{
now=++topt;
if (l==r)
{
sgt[now].sd=b[l]<?-:;
sgt[now].sv=abs(b[l]);
if (b[l]<)
{
sgt[now].mx=make_pair(b[l],l);
}else
{
sgt[now].mx=make_pair(-INFL,-);
}
return ;
}
Build_sgt(sgt[now].lc,l,smid);
Build_sgt(sgt[now].rc,smid+,r);
update(now);
}
void Add_sgt(int now,int l,int r,int x,int y,int delta)
{
if (l==x && r==y)
{
make_plus(now,l,r,delta);
return ;
}
down(now,l,r);
if (y<=smid)
Add_sgt(sgt[now].lc,l,smid,x,y,delta);
else if (smid<x)
Add_sgt(sgt[now].rc,smid+,r,x,y,delta);
else
{
Add_sgt(sgt[now].lc,l,smid,x,smid,delta);
Add_sgt(sgt[now].rc,smid+,r,smid+,y,delta);
}
update(now);
}
void Modify_sgt(int now,int l,int r,int pos,qword v)
{
if (l==r)
{
if (v<)
sgt[now].mx=make_pair(v,l);
else
sgt[now].mx=make_pair(-INFL,-);
sgt[now].sd=v<?-:;
sgt[now].sv=abs(v);
sgt[now].pls=;
return ;
}
down(now,l,r);
if (pos<=smid)
Modify_sgt(sgt[now].lc,l,smid,pos,v);
else
Modify_sgt(sgt[now].rc,smid+,r,pos,v);
update(now);
}
pair<qword,int> Query_sgt_max(int now,int l,int r,int x,int y)
{
if (l==x && r==y)
{
return sgt[now].mx;
}
down(now,l,r);
if (y<=smid)
return Query_sgt_max(sgt[now].lc,l,smid,x,y);
else if (smid<x)
return Query_sgt_max(sgt[now].rc,smid+,r,x,y);
else
return max(Query_sgt_max(sgt[now].lc,l,smid,x,smid),
Query_sgt_max(sgt[now].rc,smid+,r,smid+,y));
}
qword Query_sgt_sum(int now,int l,int r,int x,int y)
{
if (l==x && r==y)
return sgt[now].sv;
down(now,l,r);
if (y<=smid)
return Query_sgt_sum(sgt[now].lc,l,smid,x,y);
else if (smid<x)
return Query_sgt_sum(sgt[now].rc,smid+,r,x,y);
else
return Query_sgt_sum(sgt[now].lc,l,smid,x,smid)+
Query_sgt_sum(sgt[now].rc,smid+,r,smid+,y);
}
struct Edge
{
int np;
Edge *next;
}E[MAXE],*V[MAXV];
int tope=-;
void addedge(int x,int y)
{
E[++tope].np=y;
E[tope].next=V[x];
V[x]=&E[tope];
}
int q[MAXN];
int depth[MAXN],top[MAXN],son[MAXN];
int pnt[MAXN],siz[MAXN];
int pos[MAXN],dfstime;
int spos[MAXN],tpos[MAXN];
void bfs(int now)
{
int head=-,tail=;
Edge *ne;
q[]=now;
depth[now]=;
while (head<tail)
{
now=q[++head];
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
pnt[ne->np]=now;
depth[ne->np]=depth[now]+;
q[++tail]=ne->np;
}
}
for (int i=tail;i>=;i--)
{
now=q[i];
siz[now]=;
int mxsiz=;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
siz[now]+=siz[ne->np];
if (siz[ne->np]>mxsiz)
{
mxsiz=siz[ne->np];
son[now]=ne->np;
}
}
}
}
int stack[MAXN],tops=-;
void dfs(int now)
{
Edge *ne;
memset(spos,0x3f,sizeof(spos));
memset(tpos,,sizeof(tpos));
stack[++tops]=now;
top[now]=now;
while (~tops)
{
now=stack[tops--];
pos[now]=++dfstime;
tpos[top[now]]=max(tpos[top[now]],pos[now]);
spos[top[now]]=min(spos[top[now]],pos[now]);
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now] || ne->np==son[now])continue;
stack[++tops]=ne->np;
top[ne->np]=ne->np;
}
if (son[now])
{
stack[++tops]=son[now];
top[son[now]]=top[now];
}
}
}
int troot[MAXN]; int main()
{
freopen("input.txt","r",stdin);
int n,m,x,y,z;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
a[i]=nextInt();
for (int i=;i<n;i++)
{
x=nextInt();y=nextInt();
//scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
bfs();
dfs();
for (int i=;i<=n;i++)
b[pos[i]]=a[i];
for (int i=;i<=n;i++)
{
if (top[i]==i)
Build_sgt(troot[i],spos[i],tpos[i]);
else
troot[i]=-;
}
int opt;
for (int i=;i<m;i++)
{
opt=nextInt();
//scanf("%d",&opt);
if (opt==)
{
x=nextInt();y=nextInt();z=nextInt();
//scanf("%d%d%d",&x,&y,&z);
while (true)
{
if (top[x]==top[y])
{
if (pos[x]>pos[y])swap(x,y);
Add_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x],pos[y],z);
while (true)
{
pair<qword,int> pr;
pr=Query_sgt_max(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x],pos[y]);
if (pr.first<=)break;
Modify_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pr.second,pr.first);
}
break;
}
if (depth[top[x]]<depth[top[y]])swap(x,y);
Add_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x],z);
while (true)
{
pair<qword,int> pr;
pr=Query_sgt_max(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x]);
if (pr.first<=)break;
Modify_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pr.second,pr.first);
}
x=pnt[top[x]];
}
}else
{
//scanf("%d%d",&x,&y);
x=nextInt();y=nextInt();
qword res=;
while (true)
{
if (top[x]==top[y])
{
if (pos[x]>pos[y])swap(x,y);
res+=Query_sgt_sum(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x],pos[y]);
break;
}
if (depth[top[x]]<depth[top[y]])swap(x,y);
res+=Query_sgt_sum(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x]);
x=pnt[top[x]];
}
printf("%lld\n",res);
}
}
}
bzoj 4127: Abs 树链剖分的更多相关文章
- BZOJ 4127: Abs (树链剖分 线段树求区间绝对值之和 带区间加法)
题意 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d(d>=0) 2 u v 表示询问路径 (u,v) 上点权绝对值的和 分析 绝对值之和不好处理,那么我们开 ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- 【BZOJ-4127】Abs 树链剖分 + 线段树 (有趣的姿势)
4127: Abs Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 381 Solved: 132[Submit][Status][Discuss] ...
- BZOJ 3083 遥远的国度 树链剖分
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ...
- BZOJ 2157: 旅游( 树链剖分 )
树链剖分.. 样例太大了根本没法调...顺便把数据生成器放上来 -------------------------------------------------------------------- ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- BZOJ 2157 旅行(树链剖分码农题)
写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- 【bzoj4127】Abs 树链剖分+线段树
题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...
随机推荐
- try{return} finally
今天去逛论坛 时发现了一个很有趣的问题: 谁能给我我解释一下这段程序的结果为什么是:2.而不是:3? 代码如下: class Test { public int aaa() { int x = 1; ...
- box-shadow学习笔记
CSS3 box-shadow属性的简单学习笔记 语法格式: box-shadow: h-shadow v-shadow blur spread color inset; 值 描述 h-shadow ...
- SSO单点登录之跨域问题
第一次写博客,与大家共勉. 这里用到的原理其实非常简单,将cookie存在一个公共的站点的页面上就可以了,这里我们管那个站点叫主站S. 先说说所谓的跨域 环境1:a.xxx.com需要跟b.xxx.c ...
- ASP.NET MVC总结
一.概述 1.单元测试的NUnit, MBUnit, MSTest, XUnit以及其他的框架 2.ASP.NET MVC 应用的默认目录结构有三个顶层目录: Controllers.Models.V ...
- iis7下.Net框架版本设置
转载:http://blog.163.com/fan_yishan/blog/static/47692213201391651229542/ Win7下IIS网站的.Net框架版本设置 步骤/方法 1 ...
- HW--自守数
package testcase; import huawei.Demo; import junit.framework.TestCase;//加入测试框架,不需要写Main函数 public cla ...
- python 笔记(一)
1.Python优点 简单,优雅,明确 强大的模块第三方库 易移植 面向对角 可扩展 2.缺点 代码不能加密 执行速度慢 3.变量定义 第一个字母必须是字母表中的大小写,或下划线.不能以数字为开头. ...
- oracle 表空间常用语句
–查询表空间使用情况 SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)", ...
- jsp页面在IE8下文本模式自动为“杂项(Quirks)”导致页面显示错位
最近在修改网站的响应式的页面时,由于都是套样式页面,修改过程都是粘贴复制,导致了一些细节问题在IE8下暴露出来: 遇到的问题就是在在Chrome,火狐页面都正常,唯独在IE8下页面样式显示乱样了,但是 ...
- 多个UITableView横向切换的简单实现(有点类似网易新闻)
实现多列表切换,位置监控,置顶等功能. 方法一: 创建一个TableView,在切换的时候请求各类目需要的数据,然后刷新列表,通过动画模拟出滑动效果. #import <UIKit/UIKit. ...