题目大意:

给出一棵树。每一个点有商店。每一个商店都有一个价格,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. python中字典,没键加键,有键操作其键对应的值,的思想

    cars = ['鲁A32444', '鲁B12333', '京B8989M', '黑C49678', '黑C46555', '沪B25041', '黑C34567'] locations = {'沪 ...

  2. laravel之引入图片上传类

    1.在官网http://www.uploadify.com/ 下载插件,flash verison 的版本是免费版 2.解压后将文件夹放置在指定的目录下 3.前端导入css,js文件,可以仿照文件夹中 ...

  3. 微信小程序开发6-WXSS

    1.WXSS(WeiXin Style Sheets)是一套用于小程序的样式语言,用于描述WXML的组件样式,也就是视觉上的效果.WXSS与Web开发中的CSS类似.为了更适合小程序开发,WXSS对C ...

  4. *.vue文件的template标签内使用form标签

    由于form表单有重复提交的问题,所以在vue文件内直接使用form标签时需要注意这个问题,否则会导致页面重复刷新跳转不成功的问题 解决方案: <form @submit.prevent> ...

  5. [NCH 1, 3]

    Preview: 1. Implement strStr() O(m*n): class Solution { public: int strStr(string haystack,string ne ...

  6. LDF文件丢失, 如何仅用MDF文件恢复数据库呢?

    笔者的一个大小为2 TB的SQL Server的database的LDF文件在玩存储盘映射的过程中莫名其妙的丢失了. 好在MDF文件还在. 笔者慌了, Bruce Ye告诉笔者, 不用着急, 光用MD ...

  7. 关闭SSL证书验证

    转载 Python3之关闭SSL证书验证 转载 Python requests 移除SSL认证,控制台输出InsecureRequestWarning取消方法 报错信息: Traceback (mos ...

  8. 问题记录-Get data from file(fonts/arial.ttf) failed, error code is 32

    time:2015/04/19 1. 描述:运行cocos的cpp-test例子,结果修改了代码之后提示错误:Get data from file(fonts/arial.ttf) failed, e ...

  9. 克隆对象__clone()方法

    有的时候我们需要在一个项目里面,使用两个或多个一样的对象,如果你使用“new”关键字重新创建对象的话,再赋值上相同的属性,这样做比较烦琐而且也容易出错,所以要根据一个对象完全克隆出一个一模一样的对象, ...

  10. 浏览器跨域访问WebApi

      webapi地址:wapapi.ebcbuy.com web地址:wapweb.ebcbuy.com   在默认情况下这两个域名属于两个不同的域,他们之间的交互存在跨域的问题,但因为他们都同属于一 ...