记录编号 437134 评测结果 AAAAAAAA
题目名称 大话西游 最终得分 100
用户昵称 GravatarFisher. 是否通过 通过
代码语言 C++ 运行时间 0.796 s
提交时间 2017-08-13 17:47:42 内存使用 7.56 MiB
显示代码纯文本
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define ll long long 
using namespace std;
/*
	树剖,修改直接改
	查询的话,查询两个部分最值,再计算答案(答案开long long)
	查询破坏的是路。(路要存)
	分成两个部分,1--e[j]浅点,e[j].深点--n;
	以上查询是错的,
	因为是树不是链,有可能被分裂出的两个块其中一个只是一个点;
	所以不分重链进行剖分,直接维护dfs序
	子树节点在dfs序中是紧挨的
	记录一个节点dfs序,同时记录该节点子树最后一个在dfs序中的位置;
	所以查询就是1到id(深点)-1;en(深点)+1到n
	和id(深点)到en(深点)三块;
	注意别越界。 
*/
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
const int maxn=100010;
int n,m;
vector <int> t[maxn];
struct ee{int u,v;}e[maxn];
int val[maxn],fa[maxn],id[maxn],pre[maxn],tot;
int maxx[4*maxn],minn[4*maxn];
int en[maxn],dep[maxn];
inline void dfs(int u,int f,int d){
	id[u]=en[u]=++tot;pre[tot]=u;fa[u]=f;dep[u]=d;
	for(int i=0;i<t[u].size();i++){
		int v=t[u][i];
		if(v==f)continue;
		dfs(v,u,d+1);
		en[u]=max(en[u],en[v]);
	}
}
inline void build(int o,int l,int r){
	if(l==r){
		maxx[o]=minn[o]=val[pre[l]];
		return ;
	}
	int m=(l+r)>>1,ls=o<<1,rs=ls|1;
	build(ls,l,m);
	build(rs,m+1,r);
	maxx[o]=max(maxx[ls],maxx[rs]);
	minn[o]=min(minn[ls],minn[rs]);
}
inline void change(int o,int l,int r,int nl,int nr,int v){
	if(l>=nl&&r<=nr){
		maxx[o]=minn[o]=v;
		return ;
	}
	int m=(l+r)>>1,ls=o<<1,rs=ls|1;
	if(m>=nl)change(ls,l,m,nl,nr,v);
	if(m<nr)change(rs,m+1,r,nl,nr,v);
	maxx[o]=max(maxx[ls],maxx[rs]);
	minn[o]=min(minn[ls],minn[rs]);
}
inline int findmax(int o,int l,int r,int nl,int nr){
	if(l>=nl&&r<=nr){
		return maxx[o];
	}
	int ans=-0x7fffffff;
	int m=(l+r)>>1,ls=o<<1,rs=ls|1;
	if(m>=nl)ans=max(ans,findmax(ls,l,m,nl,nr));
	if(m<nr)ans=max(ans,findmax(rs,m+1,r,nl,nr));
	return ans;
}
inline int findmin(int o,int l,int r,int nl,int nr){
	if(l>=nl&&r<=nr){
		return minn[o];
	}
	int ans=0x7fffffff;
	int m=(l+r)>>1,ls=o<<1,rs=ls|1;
	if(m>=nl)ans=min(ans,findmin(ls,l,m,nl,nr));
	if(m<nr)ans=min(ans,findmin(rs,m+1,r,nl,nr));
	return ans;
}
inline ll getans(int p){
	int u=e[p].u,v=e[p].v;
	if(dep[u]>dep[v])swap(u,v);
	int max1=-0x7fffffff,max2=-0x7fffffff,min1=0x7fffffff,min2=0x7fffffff;
	max1=max(max1,findmax(1,1,tot,id[v],en[v]));
	min1=min(min1,findmin(1,1,tot,id[v],en[v]));
	if(id[v]!=1){
		max2=max(max2,findmax(1,1,tot,1,id[v]-1));
		min2=min(min2,findmin(1,1,tot,1,id[v]-1));
	}
	if(en[v]!=n){
		max2=max(max2,findmax(1,1,tot,en[v]+1,n));
		min2=min(min2,findmin(1,1,tot,en[v]+1,n));
	}
	return (ll)max1*(ll)min1+(ll)max2*(ll)min2;
}
int main(){
	freopen("westward.in","r",stdin);
	freopen("westward.out","w",stdout);
	n=read();m=read();
	for(int i=1;i<=n;i++)val[i]=read();
	for(int i=1;i<n;i++){
		e[i].u=read();e[i].v=read();
		t[e[i].u].push_back(e[i].v);
		t[e[i].v].push_back(e[i].u);  
	}
	dfs(1,0,1);
	build(1,1,tot);
	for(int i=1;i<=m;i++){
		string c;cin>>c;
		if(c=="QUERY"){
			int p=read();
			ll ans=getans(p);
			printf("%lld\n",ans);
		}
		if(c=="CHANGE"){
			int p=read(),vv=read();
			change(1,1,tot,id[p],id[p],vv);
		}
	}
	return 0;
}