记录编号 162149 评测结果 AAAAAAAAA
题目名称 [TJOI 2015] 旅游 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 2.216 s
提交时间 2015-05-14 15:06:57 内存使用 6.47 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int INF=1000000000;
#define Nil NULL
int log_2(int x){
	int ans=-1;
	while(x){
		ans++;
		x>>=1;
	}
	return ans;
}
const int SIZEN=50010;
int N;
vector<int> c[SIZEN];
int value[SIZEN]={0};
void Read(void){
	scanf("%d",&N);
	for(int i=1;i<=N;i++) scanf("%d",&value[i]);
	int a,b;
	for(int i=1;i<N;i++){
		scanf("%d%d",&a,&b);
		c[a].push_back(b);
		c[b].push_back(a);
	}
}
class Data{
public:
	int fmx,bmx;//fmx:后-前,bmx:前-后 
	int mx,mn;
	void Assign_One(int v){
		fmx=bmx=0;
		mx=mn=v;
	}
	void operator = (int v){
		Assign_One(v);
	}
	bool Empty(void)const{
		return mn==INF;
	}
	void Add(int v){
		mx+=v;
		mn+=v;
	}
	Data(int fmx_,int bmx_,int mx_,int mn_){
		fmx=fmx_;
		bmx=bmx_;
		mx=mx_;
		mn=mn_;
	}
	Data(int v){Assign_One(v);}
	Data(){
		fmx=bmx=-INF;
		mx=-INF;mn=INF;
	}
};
void print(Data d){
	cout<<"("<<d.fmx<<" "<<d.bmx<<" "<<d.mx<<" "<<d.mn<<")"<<endl;
}
Data Reverse(const Data &d){
	return Data(d.bmx,d.fmx,d.mx,d.mn);
}
Data operator + (const Data &d1,const Data &d2){
	if(d1.Empty()) return d2;
	if(d2.Empty()) return d1;
	Data d;
	d.fmx=max(d1.fmx,d2.fmx);
	d.fmx=max(d.fmx,d2.mx-d1.mn);
	d.bmx=max(d1.bmx,d2.bmx);
	d.bmx=max(d.bmx,d1.mx-d2.mn);
	d.mx=max(d1.mx,d2.mx);
	d.mn=min(d1.mn,d2.mn);
	return d;
}
class Node{
public:
	int l,r;
	Node *lc,*rc;
	Data key;
	int lazy;
	int id;
	Node(){
		lc=rc=Nil;
		lazy=0;
	}
	void Add(int v){
		key.Add(v);
		lazy+=v;
	}
	void Push_Down(void){
		if(lazy&&lc!=Nil){
			lc->Add(lazy);
			rc->Add(lazy);
			lazy=0;
		}
	}
	void Push_Up(void){
		if(lc!=Nil){
			key=lc->key+rc->key;
		}
	}
	int Query_Id(int a){
		Push_Down();
		if(l>a||r<a) return 0;
		if(l==a&&r==a) return id;
		else return lc->Query_Id(a)+rc->Query_Id(a);
	}
	Data Query(int a,int b){
		Push_Down();
		if(l>b||r<a) return Data();
		if(l>=a&&r<=b) return key;
		else return lc->Query(a,b)+rc->Query(a,b);
	}
	void Modify(int a,int b,int v){
		Push_Down();
		if(l>b||r<a) return;
		if(l>=a&&r<=b) Add(v);
		else{
			lc->Modify(a,b,v);
			rc->Modify(a,b,v);
			Push_Up();
		}
	}
};
Node *Build(int a,int b,int val[],int ids[]){
	Node *p=new Node();
	p->l=a,p->r=b;
	if(a==b){
		p->key=val[a];
		p->id=ids[a];
	}
	else{
		int mid=(a+b)/2;
		p->lc=Build(a,mid,val,ids);
		p->rc=Build(mid+1,b,val,ids);
		p->Push_Up();
	}
	return p;
}
int father[SIZEN][21]={0};
int height[SIZEN]={0};
int depth[SIZEN]={0};
int belong[SIZEN]={0};
int top[SIZEN]={0};
bool is_leaf[SIZEN]={0};
Node *root[SIZEN];
int Get_LCA(int a,int b){
	if(depth[a]<depth[b]) swap(a,b);
	int mx=log_2(N);
	for(int i=mx;i>=0;i--){
		if(depth[father[a][i]]>=depth[b]) a=father[a][i];
	}
	if(a==b) return a;
	for(int i=mx;i>=0;i--){
		if(father[a][i]!=father[b][i]){
			a=father[a][i];
			b=father[b][i];
		}
	}
	return father[a][0];
}
int Work(int a,int b,int v){
	bool inv=false;
	if(depth[a]<depth[b]) swap(a,b),inv=true;
	Data ansl,ansr;
	while(depth[a]>depth[b]){
		int d=max(depth[top[a]],depth[b]+1);
		ansl=ansl+Reverse(root[a]->Query(d,depth[a]));
		root[a]->Modify(d,depth[a],v);
		a=root[a]->Query_Id(d);
		a=father[a][0];
	}
	while(a!=b){
		int d=max(depth[top[a]],depth[top[b]]);
		ansl=ansl+Reverse(root[a]->Query(d,depth[a]));
		root[a]->Modify(d,depth[a],v);
		ansr=root[b]->Query(d,depth[b])+ansr;
		root[b]->Modify(d,depth[b],v);
		a=root[a]->Query_Id(d);
		b=root[b]->Query_Id(d);
		a=father[a][0];
		b=father[b][0];
	}
	ansl=ansl+Reverse(root[a]->Query(depth[a],depth[a]));
	root[a]->Modify(depth[a],depth[a],v);
	Data ans=ansl+ansr;
	if(inv) ans=Reverse(ans);
	int gain=max(ans.fmx,0);
	printf("%d\n",gain);
}
void Make_Tree(int x){
	depth[x]=depth[father[x][0]]+1;
	is_leaf[x]=true;
	belong[x]=x;
	for(int i=0;i<c[x].size();i++){
		int u=c[x][i];
		if(u==father[x][0]) continue;
		is_leaf[x]=false;
		father[u][0]=x;
		Make_Tree(u);
		if(height[u]>=height[x]){
			height[x]=height[u];
			belong[x]=belong[u];
		}
	}
	height[x]++;
	top[belong[x]]=x;
}
int chain_val[SIZEN]={0};
int chain_id[SIZEN]={0};
void Prepare(void){
	Make_Tree(1);
	int mx=log_2(N);
	for(int j=1;j<=mx;j++){
		for(int i=1;i<=N;i++){
			father[i][j]=father[father[i][j-1]][j-1];
		}
	}
	for(int i=1;i<=N;i++){
		if(!is_leaf[i]) continue;
		int x=i;
		while(x!=top[i]){
			chain_val[depth[x]]=value[x];
			chain_id[depth[x]]=x;
			x=father[x][0];
		}
		chain_val[depth[x]]=value[x];
		chain_id[depth[x]]=x;
		root[i]=Build(depth[top[i]],depth[i],chain_val,chain_id);
	}
	for(int i=1;i<=N;i++){
		top[i]=top[belong[i]];
		root[i]=root[belong[i]];
	}
}
int main(){
	freopen("tjoi2015_travel.in","r",stdin);
	freopen("tjoi2015_travel.out","w",stdout);
	Read();
	Prepare();
	int M,a,b,v;
	scanf("%d",&M);
	for(int i=1;i<=M;i++){
		scanf("%d%d%d",&a,&b,&v);
		Work(a,b,v);
	}
	return 0;
}