bzoj3999 [TJOI2015]旅游

Description

为了提高智商,ZJY准备去往一个新世界去旅游。这个世界的城市布局像一棵树。每两座城市之间只有一条路径可以互达。每座城市都有一种宝石,有一定的价格。ZJY为了赚取最高利益,她会选择从A城市买入再转手卖到B城市。由于ZJY买宝石时经常卖萌,因而凡是ZJY路过的城市,这座城市的宝石价格会上涨。让我们来算算ZJY旅游完之后能够赚取的最大利润。(如a城市宝石价格为v,则ZJY出售价格也为v)

Input

第一行输入一个正整数N,表示城市个数。
接下来一行输入N个正整数表示每座城市宝石的最初价格p,每个宝石的初始价格不超过100。
第三行开始连续输入N-1行,每行有两个数字x和y。表示x城市和y城市有一条路径。城市编号从1开始。
下一行输入一个整数Q,表示询问次数。
接下来Q行,每行输入三个正整数a,b,v,表示ZJY从a旅游到b,城市宝石上涨v。
1≤ N≤50000, 1≤Q ≤50000

Output

 对于每次询问,输出ZJY可能获得的最大利润,如果亏本则输出0。

Sample Input

3
1 2 3
1 2
2 3
2
1 2 100
1 3 100

Sample Output

1
1

 

正解:树链剖分+线段树。

这题还是有点代码难度的,不过想清楚再写就很容易了。。

我们考虑维护4个东西,最小值,最大值,前缀最大减后缀最小,后缀最大减前缀最小,注意线段树的叶子结点的后两个标记必须为$0$,不然会出错。

如何合并标记?前两个标记很好合并,但是后两个似乎有点麻烦。其实很简单,后两个标记的合并可以分为两部分,一部分是两个儿子的标记取最值,还有一部分是左儿子的最大值减右儿子的最小值或左儿子的最小值减右儿子的最大值,两部分都取最大值就行了。

这题区间修改很$simple$,就是最小值和最大值加上修改的$w$就行了。

考虑如何查询。我们在跳链时会扣出$logn$个区间,那么答案由两部分组成。

一部分是一个区间以内的,这个部分就是这个区间的前缀最大减后缀最小或后缀最大减前缀最小。考虑如果这个区间的右端点更靠近$a$点,那么答案就是前者,否则是后者。

另一部分是不同区间之间的。那么首先我们要对这个区间按照从$a$到$b$经过的顺序排序。所以我们肯定要对每一个区间加上标记,具体的话看看我的代码就知道了。

然后我们直接$O(log^{2}n)$地暴力枚举两两区间。易知答案就是后一个区间的最大值减去前一个区间的最小值。

对于两个部分的答案,我们直接取最大值输出就行了。

 

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <complex>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <cstdio>
  8 #include <vector>
  9 #include <cmath>
 10 #include <queue>
 11 #include <stack>
 12 #include <map>
 13 #include <set>
 14 #define inf (1<<30)
 15 #define N (100010)
 16 #define ls (x<<1)
 17 #define rs (x<<1|1)
 18 #define il inline
 19 #define RG register
 20 #define LL long long
 21 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 22 
 23 using namespace std;
 24 
 25 struct edge{ LL nt,to; }g[2*N];
 26 struct data{ LL mn,mx,ll,rr; };
 27 struct node{ LL cnt,t; data res; }q[110];
 28 
 29 LL head[N],top[N],fa[N],son[N],p[N],sz[N],dep[N],tid[N],pos[N],n,num,cnt,Q;
 30 LL lazy[4*N],mn[4*N],mx[4*N],ll[4*N],rr[4*N];
 31 
 32 il LL gi(){
 33     RG LL x=0,q=1; RG char ch=getchar();
 34     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
 35     if (ch=='-') q=-1,ch=getchar();
 36     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
 37     return q*x;
 38 }
 39 
 40 il void insert(RG LL from,RG LL to){
 41     g[++num]=(edge){head[from],to},head[from]=num; return;
 42 }
 43 
 44 il LL cmpq(const node &a,const node &b){
 45     if (a.cnt!=b.cnt) return a.cnt<b.cnt;
 46     if (a.cnt==1) return a.t<b.t; return a.t>b.t;
 47 }
 48 
 49 il void dfs1(RG LL x,RG LL p){
 50     fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG LL v;
 51     for (RG LL i=head[x];i;i=g[i].nt){
 52     v=g[i].to; if (v==p) continue;
 53     dfs1(v,x); sz[x]+=sz[v];
 54     if (sz[son[x]]<=sz[v]) son[x]=v;
 55     }
 56     return;
 57 }
 58 
 59 il void dfs2(RG LL x,RG LL p,RG LL anc){
 60     top[x]=anc,tid[x]=++cnt,pos[cnt]=x;
 61     if (son[x]) dfs2(son[x],x,anc); RG LL v;
 62     for (RG LL i=head[x];i;i=g[i].nt){
 63     v=g[i].to; if (v==p || v==son[x]) continue;
 64     dfs2(v,x,v);
 65     }
 66     return;
 67 }
 68 
 69 il void pushdown(RG LL x){
 70     mn[ls]+=lazy[x],mn[rs]+=lazy[x];
 71     mx[ls]+=lazy[x],mx[rs]+=lazy[x];
 72     lazy[ls]+=lazy[x],lazy[rs]+=lazy[x];
 73     lazy[x]=0; return;
 74 }
 75 
 76 il void merge(RG LL x,RG LL l,RG LL r){
 77     ll[x]=max(ll[ls],ll[rs]),ll[x]=max(ll[x],mx[ls]-mn[rs]);
 78     rr[x]=max(rr[ls],rr[rs]),rr[x]=max(rr[x],mx[rs]-mn[ls]);
 79     mn[x]=min(mn[ls],mn[rs]),mx[x]=max(mx[ls],mx[rs]); return;
 80 }
 81 
 82 il void build(RG LL x,RG LL l,RG LL r){
 83     if (l==r){ mn[x]=mx[x]=p[pos[l]]; return; }
 84     RG LL mid=(l+r)>>1; build(ls,l,mid),build(rs,mid+1,r);
 85     merge(x,l,r); return;
 86 }
 87 
 88 il void update(RG LL x,RG LL l,RG LL r,RG LL xl,RG LL xr,RG LL v){
 89     if (xl<=l && r<=xr){ mn[x]+=v,mx[x]+=v,lazy[x]+=v; return; }
 90     if (lazy[x]) pushdown(x); RG LL mid=(l+r)>>1;
 91     if (xr<=mid) update(ls,l,mid,xl,xr,v);
 92     else if (xl>mid) update(rs,mid+1,r,xl,xr,v);
 93     else update(ls,l,mid,xl,mid,v),update(rs,mid+1,r,mid+1,xr,v);
 94     merge(x,l,r); return;
 95 }
 96 
 97 il data query(RG LL x,RG LL l,RG LL r,RG LL xl,RG LL xr){
 98     if (xl<=l && r<=xr) return (data){mn[x],mx[x],ll[x],rr[x]};
 99     if (lazy[x]) pushdown(x); RG LL mid=(l+r)>>1;
100     if (xr<=mid) return query(ls,l,mid,xl,xr);
101     else if (xl>mid) return query(rs,mid+1,r,xl,xr);
102     else{
103     RG data res1=query(ls,l,mid,xl,mid);
104     RG data res2=query(rs,mid+1,r,mid+1,xr);
105     RG LL ll=max(res1.ll,res2.ll); ll=max(ll,res1.mx-res2.mn);
106     RG LL rr=max(res1.rr,res2.rr); rr=max(rr,res2.mx-res1.mn);
107     RG LL mn=min(res1.mn,res2.mn),mx=max(res1.mx,res2.mx);
108     return (data){mn,mx,ll,rr};
109     }
110 }
111 
112 il void change(RG LL u,RG LL v,RG LL w){
113     while (top[u]!=top[v]){
114     if (dep[top[u]]<dep[top[v]]) swap(u,v);
115     update(1,1,n,tid[top[u]],tid[u],w),u=fa[top[u]];
116     }
117     if (dep[u]>dep[v]) swap(u,v);
118     update(1,1,n,tid[u],tid[v],w); return;
119 }
120 
121 il LL Query(RG LL u,RG LL v){
122     RG LL uu=0,vv=0,cntu=1,cntv=2,cnt=0,res=0;
123     while (top[u]!=top[v]){
124     if (dep[top[u]]<dep[top[v]])
125         swap(u,v),swap(uu,vv),swap(cntu,cntv);
126     q[++cnt]=(node){cntu,++uu,query(1,1,n,tid[top[u]],tid[u])};
127     u=fa[top[u]];
128     }
129     if (dep[u]>dep[v]) swap(u,v),swap(uu,vv),swap(cntu,cntv);
130     q[++cnt]=(node){cntv,++vv,query(1,1,n,tid[u],tid[v])};
131     sort(q+1,q+cnt+1,cmpq);
132     for (RG LL i=1;i<=cnt;++i)
133     if (q[i].cnt==1) res=max(res,q[i].res.ll);
134     else res=max(res,q[i].res.rr);
135     for (RG LL i=1;i<cnt;++i)
136     for (RG LL j=i+1;j<=cnt;++j)
137         res=max(res,q[j].res.mx-q[i].res.mn);
138     return res;
139 }
140 
141 il void work(){
142     n=gi();
143     for (RG LL i=1;i<=n;++i) p[i]=gi();
144     for (RG LL i=1,u,v;i<n;++i)
145     u=gi(),v=gi(),insert(u,v),insert(v,u);
146     dfs1(1,0),dfs2(1,0,1),build(1,1,n),Q=gi();
147     for (RG LL i=1,u,v,w;i<=Q;++i){
148     u=gi(),v=gi(),w=gi();
149     printf("%lld\n",Query(u,v));
150     change(u,v,w);
151     }
152     return;
153 }
154 
155 int main(){
156     File("travel");
157     work();
158     return 0;
159 }

 

posted @ 2017-04-13 22:33  wfj_2048  阅读(233)  评论(0编辑  收藏  举报