题目大意:

给出一棵树。每一个点有商店。每一个商店都有一个价格,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(树链剖分)的更多相关文章

  1. HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online

    意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...

  2. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  3. 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 ...

  4. HDU 5274 Dylans loves tree(树链剖分)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5274 [题目大意] 给出一棵树,每个点有一个权值,权值可修改,且大于等于0,询问链上出现次数为奇数 ...

  5. hdu 3966 Aragorn&#39;s Story(树链剖分+树状数组)

    pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...

  6. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  7. HDU - 3966 Aragorn's Story(树链剖分入门+线段树)

    HDU - 3966 Aragorn's Story Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  8. (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。

    Problem Description   Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...

  9. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...

随机推荐

  1. Line Numbers for RichText Control in C#

    from: http://www.codeproject.com/Articles/38858/Line-Numbers-for-RichText-Control-in-C using Microso ...

  2. js 中concat()和slice()方法介绍

    1.concat() concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. <script type="text/javascr ...

  3. 前端面试题1(html)

    HTML     * Doctype作用?严格模式与混杂模式如何区分?它们有何意义? 1.<!DOCTYPE> 声明位于文档中的最前面的位置,处于 <html> 标签之前.此标 ...

  4. 爬虫必备—requests

    Requests 是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP 库,其在Python内置模块的基础上进行了高度的封装,从而使得Pythoner进行网络请求时,变得 ...

  5. Wasserstein GAN最新进展:从weight clipping到gradient penalty,更加先进的Lipschitz限制手法

    前段时间,Wasserstein GAN以其精巧的理论分析.简单至极的算法实现.出色的实验效果,在GAN研究圈内掀起了一阵热潮(对WGAN不熟悉的读者,可以参考我之前写的介绍文章:令人拍案叫绝的Was ...

  6. Android 编辑框插入表情图片

    首先,把整理好的表情图片以及布局用到的一些图片导入到项目的res/drawable目录中. 然后,编辑res/layout目录下布局.xml文件,这里我把oschina客户端的布局代码贴上来,供大家参 ...

  7. @WebServlet

    编写好Servlet之后,接下来要告诉Web容器有关于这个Servlet的一些信息.在Servlet 3.0中,可以使用标注(Annotation)来告知容器哪些Servlet会提供服务以及额外信息. ...

  8. php 3des加密 兼容JAVA 多么痛的领悟呀

    最近和别人做接口用到SOCKET TCP/IP方式 其中需要对账号和密码进行3DES加密 对方提供了一个加密比对的软件和JAVA的实现代码 并且给了我们一个长度为32位的密钥 这边需要用PHP来实现! ...

  9. 产品从生到死的N宗罪

    写在前面 昨天晚上做了一个梦,大概就是跟CTO,PM在说着什么..现在回想起好像就是说产品怎么怎么的..:索性就吐槽下这几个项目生与死的N宗罪吧.. 特别提示: 本文为全方位吐槽型,前方多处具有针对性 ...

  10. Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.

    In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...