題意:給定一棵有點權的樹。
支持操作:
1.修改(u,v)這條路徑上的點權
2.詢問(u,v)這條路徑上的連續的點權的最大值。
這道題應該可以用樹鏈剖分做。不過鑑於我正在學LCT那就用LCT好了~
應該算是比較裸的LCT了吧。維護lmax、rmax、smax、sum即可回答。修改的時候打個標記就行。
Vijos上0.6s,SPOJ上17s。。這什麼差距。。
貼代碼~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 0x7fffffff
#define max(a,b) (((a)>(b))?(a):(b))
struct LinkCutTree{
#define S 200010
int pp[S],ch[S][2],fa[S],val[S],sz[S],lmax[S],rmax[S],smax[S],sum[S],same[S];
#define ls ch[x][0]
#define rs ch[x][1]
inline void pushup(int x){
sz[x]=sz[ls]+sz[rs]+1;
sum[x]=sum[ls]+sum[rs]+val[x];
lmax[x]=max(lmax[ls],sum[ls]+val[x]+lmax[rs]);
rmax[x]=max(rmax[rs],sum[rs]+val[x]+rmax[ls]);
smax[x]=max(max(smax[ls],smax[rs]),rmax[ls]+val[x]+lmax[rs]);
}
inline void pushdown(int x){
if(same[x]!=inf){
if(ls){
same[ls]=val[ls]=same[x];
sum[ls]=same[x]*sz[ls];
lmax[ls]=rmax[ls]=smax[ls]=max(sum[ls],0);
}
if(rs){
same[rs]=val[rs]=same[x];
sum[rs]=same[x]*sz[rs];
lmax[rs]=rmax[rs]=smax[rs]=max(sum[rs],0);
}
same[x]=inf;
}
}
inline void rotate(int x,int f){
int y=fa[x],z=fa[y];
pushdown(y);
pushdown(x);
ch[y][!f]=ch[x][f];
fa[ch[x][f]]=y;
ch[z][ch[z][1]==y]=x;
fa[x]=z;
ch[x][f]=y;
fa[y]=x;
pushup(y);
}
inline void splay(int x){
int p;
for(p=x;fa[p];p=fa[p]);
if(p!=x){
pp[x]=pp[p];
pp[p]=0;
while(fa[x]) rotate(x,ch[fa[x]][0]==x);
pushup(x);
}else pushdown(x);
}
inline void access(int x){
for(int p=0;x;x=pp[x]){
splay(x);
pp[rs]=x;
fa[rs]=0;
rs=p;
pp[rs]=0;
fa[rs]=x;
p=x;
pushup(x);
}
}
inline void update(int x,int y,int v){
access(y);
for(y=0;x;x=pp[x]){
splay(x);
if(!pp[x]){
val[x]=v;
if(y){
val[y]=same[y]=v;
sum[y]=v*sz[y];
lmax[y]=rmax[y]=smax[y]=max(0,v);
}
if(rs){
y=rs;
val[y]=same[y]=v;
sum[y]=v*sz[y];
lmax[y]=rmax[y]=smax[y]=max(0,v);
}
}
pp[rs]=x;
fa[rs]=0;
rs=y;
fa[rs]=x;
pp[rs]=0;
y=x;
pushup(x);
}
}
inline int query(int x,int y){
int ans;
access(y);
for(y=0;x;x=pp[x]){
splay(x);
if(!pp[x]) return max(max(smax[y],smax[rs]),val[x]+lmax[y]+lmax[rs]);
pp[rs]=x;
fa[rs]=0;
rs=y;
fa[rs]=x;
pp[rs]=0;
y=x;
pushup(x);
}
return 0;
}
}LCT;
#define maxn 200010
#define maxm 400020
struct edge{
int t,next;
}E[maxm];
int V[maxn],tot=0;
inline void addedge(int x,int y){
E[tot].t=y;E[tot].next=V[x];V[x]=tot++;
}
int vis[maxn],q[maxn];
inline void bfs(int x){
int head=0,tail=1;
memset(vis,0,sizeof(vis));
vis[x]=true;
q[head]=x;
while(head!=tail){
int u=q[head++];
for(int p=V[u];p!=-1;p=E[p].next){
int v=E[p].t;
if(!vis[v]){
LCT.pp[v]=u;
LCT.same[v]=inf;
vis[v]=true;
q[tail++]=v;
}
}
}
}
inline void init(){
memset(V,0xff,sizeof(V));
tot=0;
}
inline void read(int &x){
char ch; int f=1;
for(ch=getchar();(ch!='-')&&(ch<'0'||ch>'9');ch=getchar());
if(ch=='-') f=-1,x=0; else x=ch-'0';
for(ch=getchar();ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
x*=f;
}
int main(){
int n,u,v,x,y,q,op;
read(n);
init();
for(int i=1;i<=n;i++){
read(LCT.val[i]);
LCT.same[i]=inf;
}
for(int i=1;i<n;i++){
read(u);
read(v);
addedge(u,v);
addedge(v,u);
}
bfs(1);
read(q);
int flag=0;
while(q--){
read(op);
if(op==1){
read(x);
read(y);
if(flag)printf(" "); else flag=1;
printf("%d",LCT.query(x,y));
}else{
read(x);
read(y);
read(v);
LCT.update(x,y,v);
}
}
printf("\n");
return 0;
}