Hdu 5052 Yaoge’s maximum profit(树链剖分)
题目大意:
给出一棵树。每一个点有商店。每一个商店都有一个价格,Yaoge每次从x走到y都能够在一个倒卖商品,从中得取利益。当然,买一顶要在卖之前。可是没次走过一条路,这条路上的全部商品都会添加一个v。
输出每次的最大利益。
思路分析:
非常easy想到树链剖分,但是关键在于怎样维护这样一个变量。使得每次都要让买的再卖的前面。
维护变量 ltr 和 rtl 。表示从左去右和从右去左。
剖分熟练的时候。推断x 和 y的深度,一步一步往上爬。
然后维护区间最大值和最小值。爬的时候更新答案。
。。。4921ms...小孩子不要看。。。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#pragma comment(linker,"/STACk:10240000,10240000")
#define maxn 50005
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
using namespace std;
typedef long long ll;
int next[maxn<<1],to[maxn<<1],head[maxn],tot;//临界表
int pre[maxn],root[maxn],siz[maxn],son[maxn],w[maxn],dep[maxn],id;//原树的父亲 链上的根 siz 有最大siz的子树 又一次分配的id 深度 getid中来计数的
ll ltr[maxn<<2],rtl[maxn<<2],mx[maxn<<2],mn[maxn<<2],add[maxn<<2];//线段树变量
int n;
void init()
{
pre[1]=0;
dep[1]=0;
tot=0;id=0;
memset(head,0,sizeof head);
memset(add,0,sizeof add);
memset(mn,0,sizeof mn);
memset(mx,0,sizeof mx);
memset(ltr,0,sizeof ltr);
memset(rtl,0,sizeof rtl);
}
void addedge(int u,int v)
{
tot++;
next[tot]=head[u];
to[tot]=v;
head[u]=tot;
}
void dfs(int now)//to get size,son,dep,pre...
{
son[now]=0;
siz[now]=1;
for(int p =head[now]; p ; p=next[p])
{
int t=to[p];
if(t!=pre[now])
{
pre[t]=now;
dep[t]=dep[now]+1;
dfs(t);
if(siz[t]>siz[son[now]])son[now]=t;
siz[now]+=siz[t];
}
}
}
void getid(int now,int rt)//to get w and root...
{
w[now]=++id;
root[now]=rt;
if(son[now])getid(son[now],rt);
for(int p = head[now] ; p ; p=next[p])
{
int t=to[p];
if(t!=son[now]&&t!=pre[now])
getid(t,t);
}
}
void pushdown(int num,int s,int e)
{
if(add[num])
{
int mid=(s+e)>>1;
mx[num<<1]+=add[num];
mx[num<<1|1]+=add[num];
mn[num<<1]+=add[num];
mn[num<<1|1]+=add[num];
add[num<<1]+=add[num];
add[num<<1|1]+=add[num];
add[num]=0;
}
}
void pushup(int num)
{
mx[num]=max(mx[num<<1],mx[num<<1|1]);
mn[num]=min(mn[num<<1],mn[num<<1|1]);
ltr[num]=max(mx[num<<1|1]-mn[num<<1],max(ltr[num<<1],ltr[num<<1|1]));
rtl[num]=max(mx[num<<1]-mn[num<<1|1],max(rtl[num<<1],rtl[num<<1|1]));
if(ltr[num]<0)ltr[num]=0;
if(rtl[num]<0)rtl[num]=0;
} void update(int num,int s,int e,int l,int r,int val)
{
if(l<=s && r>=e)
{
add[num]+=val;
mx[num]+=val;
mn[num]+=val;
return;
}
pushdown(num,s,e);
int mid=(s+e)>>1;
if(l<=mid)update(lson,l,r,val);
if(r>mid)update(rson,l,r,val);
pushup(num);
}
ll query(int num,int s,int e,int l,int r,int flg,ll &maxv,ll &minv)
{
if(l<=s && r>=e)
{
maxv=mx[num];
minv=mn[num];
if(flg)return ltr[num];
else return rtl[num];
}
int mid=(s+e)>>1;
pushdown(num,s,e);
if(r<=mid)return query(lson,l,r,flg,maxv,minv);
else if(l>mid)return query(rson,l,r,flg,maxv,minv);
else
{
ll r1,r2,n1,n2,m1,m2,ans;
r1=query(lson,l,mid,flg,m1,n1);
r2=query(rson,mid+1,r,flg,m2,n2);
maxv=max(m1,m2);
minv=min(n1,n2);
if(flg)
{
ans=max(r1,r2);
ans=max(ans,m2-n1);
}
else
{
ans=max(r1,r2);
ans=max(ans,m1-n2);
}
ans=max(0LL,ans);
return ans;
}
} ll fuck(int x,int y)
{
ll ans=0,maxx,minx,maxy,miny,rx,ry;
ll tmax,tmin,tr;
maxx=maxy=0;
minx=miny=Inf;
rx=ry=0;
while(root[x]!=root[y])
{
if(dep[root[x]]<dep[root[y]])
{
tr=query(1,1,n,w[root[y]],w[y],1,tmax,tmin);
ry=max(ry,tr);
ry=max(ry,maxy-tmin);
maxy=max(maxy,tmax);
miny=min(miny,tmin);
ans=max(ans,ry);
y=pre[root[y]];
}
else
{
tr=query(1,1,n,w[root[x]],w[x],0,tmax,tmin);
rx=max(rx,tr);
rx=max(rx,tmax-minx);
maxx=max(tmax,maxx);
minx=min(tmin,minx);
ans=max(ans,rx);
x=pre[root[x]];
}
}
if(dep[x]<dep[y])
{
tr=query(1,1,n,w[x],w[y],1,tmax,tmin);
ans=max(ans,tr);
ans=max(ans,maxy-tmin);
maxy=max(tmax,maxy);
miny=min(tmin,miny);
ans=max(ans,maxy-minx);
}
else
{
tr=query(1,1,n,w[y],w[x],0,tmax,tmin);
ans=max(ans,tr);
ans=max(ans,tmax-minx);
maxx=max(tmax,maxx);
minx=min(tmin,minx);
ans=max(ans,maxy-minx);
}
return ans;
}
void work(int x,int y,int val)
{
while(root[x]!=root[y])
{
if(dep[root[x]]<dep[root[y]])swap(x,y);
update(1,1,n,w[root[x]],w[x],val);
x=pre[root[x]];
}
if(dep[x]>dep[y])swap(x,y);
update(1,1,n,w[x],w[y],val);
}
int save[maxn]; inline void scanf_(int &num){
char in;
bool neg=false;
while(((in=getchar()) > '9' || in<'0') && in!='-') ;
if(in=='-'){
neg=true;
while((in=getchar()) >'9' || in<'0');
}
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
if(neg)
num=0-num;
}
inline void printf_(ll num){
bool flag=false;
if(num<0){
putchar('-');
num=-num;
}
int ans[20],top=0;
while(num!=0){
ans[top++]=num%10;
num/=10;
}
if(top==0)
putchar('0');
for(int i=top-1;i>=0;i--){
char ch=ans[i]+'0';
putchar(ch);
}
puts("");
} int main()
{
int T;
scanf_(T);
while(T--)
{
init();
scanf_(n);
for(int i=1;i<=n;i++)
scanf_(save[i]);
for(int i=1;i<=n-1;i++)
{
int s,e;
scanf_(s);scanf_(e);
addedge(s,e);
addedge(e,s);
}
dfs(1);
getid(1,1);
for(int i=1;i<=n;i++)
update(1,1,n,w[i],w[i],save[i]);
char str[5];
int Q;
scanf_(Q);
while(Q--)
{
int x,y,v;
scanf_(x);
scanf_(y);
scanf_(v);
printf_(fuck(x,y));
work(x,y,v);
}
}
return 0;
}
Hdu 5052 Yaoge’s maximum profit(树链剖分)的更多相关文章
- HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online
意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...
- HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- HDU 4897 Little Devil I(树链剖分)(2014 Multi-University Training Contest 4)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4897 Problem Description There is an old country and ...
- HDU 5274 Dylans loves tree(树链剖分)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5274 [题目大意] 给出一棵树,每个点有一个权值,权值可修改,且大于等于0,询问链上出现次数为奇数 ...
- hdu 3966 Aragorn's Story(树链剖分+树状数组)
pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- HDU - 3966 Aragorn's Story(树链剖分入门+线段树)
HDU - 3966 Aragorn's Story Time Limit: 3000MS Memory Limit: 32768KB 64bit IO Format: %I64d & ...
- (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。
Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...
- hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...
随机推荐
- webpack打包踩坑之TypeError: Cannot read property 'bindings' of null
file loader介绍:https://www.webpackjs.com/loaders/file-loader/ babel loader介绍:https://webpack.js.org/l ...
- Java设计模式—命令模式
命令模式是一个高内聚的模式. 定义如下:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 通用类图如下: 角色说明: ● Re ...
- 使用SVG中的Symbol元素制作Icon【摘转】
以下为内容摘抄和转摘记录: 为什么要用svg ? SVG优势 随着高清屏幕的普及,相比使用png等位图而言,使用SVG等矢量图形是一种全新的设计方式.更重要的是相比位图而言,SVG有着无可比拟的优势. ...
- 编辑文本(EditText)
今天要给大家介绍的是简单的编辑文本框: 先看一下它的基本属性: 1.Activity public class EditTextActivity extends Activity { private ...
- 131.004 监督学习项目 | 为CharityML寻找捐献者
监督学习: 为CharityML寻找捐献者 开始 在这个项目中,你将使用1994年美国人口普查收集的数据,选用几个监督学习算法以准确地建模被调查者的收入.然后,你将根据初步结果从中选择出最佳的候选 ...
- 当EditText编辑时 hint 在 6.0 手机上显示不出来
当EditText编辑时 hint 在 6.0 手机上显示不出来.... 就要增加一句话去重新设置颜色值 Android:textColorHint = "#707070"
- AutoMapper6扩展
简介 很多时候我们使用AutoMapper的时候,都需要进行一个配置才可以使用Mapper.Map<Source,Target>(entity);.如果不进行配置则会报错. 如果实体过多, ...
- Androidpdf
https://www.jb51.net/article/110238.htm https://blog.csdn.net/u010046908/article/details/53927157 &l ...
- python之路——进程
操作系统背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其 ...
- [BZOJ 4573][ZJOI 2016]大森林
[LOJ 2092][BZOJ 4573][UOJ 195][ZJOI 2016]大森林 题意 给定一个树序列, 初始时所有树都只有一个点, 要求支持三种操作: 区间种树(在某个特定点上长出一个子结点 ...