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
题目大意就是给定起点和终点,求这条路径上的最大值减最小值,最小值要在最大值的前面。还有单点修改操作。
先树链剖分。
对于剖出来的几段路径,分情况讨论。
设路径是从x到y。
对于一段x到LCA的路径,max-前面查询的最小值,y到LCA的路径的最大值-min可以更新答案。
y到LCA的路径类似。
还要考虑线段树中的可以更新答案的情况,维护两个东西:左区间-右区间的最大和右区间-左区间的最大就可以了。
实现很麻烦啊。
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\n",solve(x,y)); 156 else change(1,1,n,dfn[x],y); 157 } 158 return 0; 159 }