codevs水果姐逛水果街3

3306 水果姐逛水果街Ⅲ

 

时间限制: 2 s
空间限制: 256000 KB
题目等级 : 大师 Master
 
 
 
题目描述 Description

连续两天都没有被cgh难倒,水果姐心情很不错,第三天又来逛水果街。

今天cgh早早就来到了水果街等水果姐,因为他带来了帮手cys。cgh的魔法是把水果街变成树结构,而cys的魔法是瞬间改变某家店的水果价格。一边问一边改,绝不给水果姐思考的时间!

同样还是n家水果店,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样。

cgh和cys一共有m个操作。

操作的格式为

0 x y 获 1 x y

如果操作类型是0,表示cys把第x家店的价格改为y

如果操作类型是1,则表示要求水果姐从第x家店出发到第y家店,途中只能选一家店买一个水果,然后选一家店(可以是同一家店,但不能往回走)卖出去。并且输出最多可以赚多少钱。

这题是给天牛做的。

输入描述 Input Description

第一行n,表示有n家店

下来n个正整数,表示每家店一个苹果的价格。

下来n-1行,每行两个整数x,y,表示第x家店和第y家店有一条边。

下来一个整数m,表示下来有m个操作。

下来有m行,每行三个整数,表示一次操作。

输出描述 Output Description

每行对应一个1类型的操作,输出一个整数,表示面对cgh的每次询问,水果姐最多可以赚到多少钱。

样例输入 Sample Input

4
16 5 1 15
1 2
1 3
2 4
3
1 3 4
0 3 17
1 4 3

样例输出 Sample Output

15
12

数据范围及提示 Data Size & Hint

0<=苹果的价格<=10^8

0<n<=2*10^5

0<m<=10^5

题目大意就是给定起点和终点,求这条路径上的最大值减最小值,最小值要在最大值的前面。还有单点修改操作。
先树链剖分。
对于剖出来的几段路径,分情况讨论。
设路径是从xy
对于一段xLCA的路径,max-前面查询的最小值,yLCA的路径的最大值-min可以更新答案。
yLCA的路径类似。
还要考虑线段树中的可以更新答案的情况,维护两个东西:左区间-右区间的最大和右区间-左区间的最大就可以了。
实现很麻烦啊。
  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #define maxn 500100
  8 #define ls o*2
  9 #define rs o*2+1
 10 #define mi int mid=(l+r)>>1
 11 #define inf 1999999999
 12 using namespace std;
 13 struct data{
 14   int nex,to;
 15 }e[maxn*2];
 16 int n,head[maxn],edge=0,dad[maxn],son[maxn],size[maxn],top[maxn],dfn[maxn],dfp[maxn],deep[maxn],dis[maxn];
 17 int b1[maxn*4],b2[maxn*4],b3[maxn*4],b4[maxn*4];
 18 int max(int x,int y){return x<y?y:x;}
 19 int min(int x,int y){return x<y?x:y;}
 20 void add(int from,int to){
 21   e[++edge].nex=head[from];
 22   e[edge].to=to;
 23   head[from]=edge;
 24 }
 25 void build(int o,int l,int r){
 26   if(l==r){b1[o]=b2[o]=dis[dfp[l]];return;}
 27   mi;
 28   build(ls,l,mid);
 29   build(rs,mid+1,r);
 30   b1[o]=min(b1[ls],b1[rs]);
 31   b2[o]=max(b2[ls],b2[rs]);
 32   b3[o]=max(b2[rs]-b1[ls],max(b3[ls],b3[rs]));
 33   b4[o]=max(b2[ls]-b1[rs],max(b4[ls],b4[rs]));
 34 }
 35 void dfs1(int x,int fa){
 36   size[x]++;
 37   for(int i=head[x];i;i=e[i].nex){
 38     int u=e[i].to;
 39     if(u==fa) continue;
 40     deep[u]=deep[x]+1;
 41     dad[u]=x;
 42     dfs1(u,x);
 43     size[x]+=size[u];
 44     if(size[u]>size[son[x]])son[x]=u;
 45   }
 46 }
 47 int de=0;
 48 void dfs2(int x,int fa){
 49   ++de;
 50   dfn[x]=de,dfp[de]=x;
 51   if(son[x]){
 52     top[son[x]]=top[x];
 53     dfs2(son[x],x);
 54   }
 55   for(int i=head[x];i;i=e[i].nex){
 56     int u=e[i].to;
 57     if(u==fa || u==son[x]) continue;
 58     top[u]=u;
 59     dfs2(u,x);
 60   }
 61 }
 62 void change(int o,int l,int r,int p,int w){
 63   if(l==r){b1[o]=b2[o]=w;return;}
 64   mi;
 65   if(p<=mid) change(ls,l,mid,p,w);
 66   else change(rs,mid+1,r,p,w);
 67   b1[o]=min(b1[ls],b1[rs]);
 68   b2[o]=max(b2[ls],b2[rs]);
 69   b3[o]=max(b2[rs]-b1[ls],max(b3[ls],b3[rs]));
 70   b4[o]=max(b2[ls]-b1[rs],max(b4[ls],b4[rs]));
 71 }
 72 int find_max(int o,int l,int r,int u,int v){
 73   if(l>=u && r<=v) return b2[o];
 74   if(l>v || r<u) return 0;
 75   mi;
 76   if(v<=mid) return find_max(ls,l,mid,u,v);
 77   else if(u>mid) return find_max(rs,mid+1,r,u,v);
 78   else return max(find_max(ls,l,mid,u,mid),find_max(rs,mid+1,r,mid+1,v));
 79 }
 80 int find_min(int o,int l,int r,int u,int v){
 81   if(l>=u && r<=v) return b1[o];
 82   if(l>v || r<u) return inf;
 83   mi;
 84   if(v<=mid) return find_min(ls,l,mid,u,v);
 85   else if(u>mid) return find_min(rs,mid+1,r,u,v);
 86   else return min(find_min(ls,l,mid,u,mid),find_min(rs,mid+1,r,mid+1,v));
 87 }
 88 int find_ans1(int o,int l,int r,int u,int v){
 89   if(l>=u && r<=v) return b4[o];
 90   if(l>v || r<u) return 0;
 91   int mid=(l+r)>>1;
 92   if(v<=mid) return find_ans1(ls,l,mid,u,v);
 93   else if(u>mid) return find_ans1(rs,mid+1,r,u,v);
 94   else return max(max(find_ans1(ls,l,mid,u,mid),find_ans1(rs,mid+1,r,mid+1,v)),
 95           find_max(1,1,n,u,mid)-find_min(1,1,n,mid+1,v));
 96 }
 97 int find_ans2(int o,int l,int r,int u,int v){
 98   if(l>=u && r<=v) return b3[o];
 99   if(l>v || r<u) return 0;
100   int mid=(l+r)>>1;
101   if(v<=mid) return find_ans2(ls,l,mid,u,v);
102   else if(u>mid) return find_ans2(rs,mid+1,r,u,v);
103   else return max(max(find_ans2(ls,l,mid,u,mid),find_ans2(rs,mid+1,r,mid+1,v)),
104           find_max(1,1,n,mid+1,v)-find_min(1,1,n,u,mid));
105 }
106 int solve(int x,int y){
107   int ans=0,zd1=0,zd2=0,zx1=inf,zx2=inf;
108   while(top[x]!=top[y]){
109     if(deep[top[x]]>deep[top[y]]){
110       int k1=find_max(1,1,n,dfn[top[x]],dfn[x]);
111       zd1=max(zd1,k1);
112       ans=max(ans,find_ans1(1,1,n,dfn[top[x]],dfn[x]));
113       ans=max(ans,k1-zx1);
114       int k2=find_min(1,1,n,dfn[top[x]],dfn[x]);
115       zx1=min(zx1,k2);
116       ans=max(ans,zd2-k2);
117       x=dad[top[x]];
118     }
119     else{
120       int k1=find_min(1,1,n,dfn[top[y]],dfn[y]);
121       zx2=min(zx2,k1);
122       ans=max(ans,find_ans2(1,1,n,dfn[top[y]],dfn[y]));
123       ans=max(ans,zd2-k1);
124       int k2=find_max(1,1,n,dfn[top[y]],dfn[y]);
125       zd2=max(zd2,k2);
126       ans=max(ans,k2-zx1);
127       y=dad[top[y]];
128     }
129   }
130   if(deep[x]>deep[y])
131     ans=max(ans,find_ans1(1,1,n,dfn[y],dfn[x]));
132   else ans=max(ans,find_ans2(1,1,n,dfn[x],dfn[y]));
133   if(deep[x]>deep[y])swap(x,y);
134   int zx=find_min(1,1,n,dfn[x],dfn[y]);
135   int zd=find_max(1,1,n,dfn[x],dfn[y]);
136   ans=max(ans,zd-zx1);
137   ans=max(ans,zd2-zx);
138   return ans;
139 }
140 int main()
141 {
142   int x,y,qes;
143   scanf("%d",&n);
144   for(int i=1;i<=n;i++) scanf("%d",&dis[i]);
145   for(int i=1;i<n;i++)
146     scanf("%d%d",&x,&y),add(x,y),add(y,x);
147   scanf("%d",&qes);
148   dad[1]=1,top[1]=1;
149   dfs1(1,0);dfs2(1,0);
150   build(1,1,n);
151   for(int i=1;i<=qes;i++){
152     int type;
153     scanf("%d%d%d",&type,&x,&y);
154     if(type)
155       printf("%d
",solve(x,y));
156       else change(1,1,n,dfn[x],y);
157   }
158   return 0;
159 }







原文地址:https://www.cnblogs.com/pantakill/p/6708369.html