hdu 5052 (LCT)

/*
一颗树,有n个点,每个点有一个权值。
每次查询 u->v 的路径上(u,v,w) 先取一个点权,在取一个点权,使后者减去前者的值最大(如果为负数,输出0),并且走过这条路

径之后,路径上每个点的点权都加上w。
*/
//下面的代码是修改模板之后的,里面有好多函数是没有用到的,与模板有很好的继承性

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 50010;
struct Node *null;
struct Node{
	Node *fa,*ch[2];
	int val,size;  //val是该点的权重,size是以它为根的子树的大小。
	int add;
	int mm;
	int Max,Min;
	int rmm;
	int rev;
	inline void clear(int _val){  //初始化该点的点权。
		fa = ch[0] = ch[1] = null;
		val = Max = Min = _val;
		mm = 0;
		rmm = 0;
		rev = 0;
		add = 0;
	}
	inline void push_up(){    //
		if(this == null)return;
		mm = 0;
		mm = max(mm,ch[0]->mm);
		mm = max(mm,ch[1]->mm);
		mm = max(mm,max(val,ch[1]->Max)-ch[0]->Min);
		mm = max(mm,ch[1]->Max-min(ch[0]->Min,val));
		rmm = 0;
		rmm = max(rmm,ch[0]->rmm);
		rmm = max(rmm,ch[1]->rmm);
		rmm = max(rmm,max(val,ch[0]->Max)-ch[1]->Min);
		rmm = max(rmm,ch[0]->Max-min(ch[1]->Min,val));
		Max = max(val,max(ch[0]->Max,ch[1]->Max));
		Min = min(val,min(ch[0]->Min,ch[1]->Min));
	}
	inline void setc(Node *p,int d){
		ch[d] = p;
		p->fa = this;
	}
	inline bool d(){
		return fa->ch[1] == this;
	}
	inline bool isroot(){
		return fa == null || fa->ch[0] != this && fa->ch[1] != this;
	}
	inline void flip(){
		if(this == null)return;
		swap(ch[0],ch[1]);
		swap(mm,rmm);
		rev ^= 1;
	}
	inline void update_add(int w){
		if(this == null)return;
		val += w;
		Min += w;
		Max += w;
		add += w;
	}
	inline void push_down(){
		if(this == null)return;
		if(rev){
			ch[0]->flip(); ch[1]->flip(); rev = 0;
		}
		if(add){
			ch[0]->update_add(add);ch[1]->update_add(add);
			add = 0;
		}
	}
	inline void go(){
		if(!isroot())fa->go();
		push_down();
	}
	inline void rot(){
		Node *f = fa, *ff = fa->fa;
		int c = d(), cc = fa->d();
		f->setc(ch[!c],c);
		this->setc(f,!c);
		if(ff->ch[cc] == f)ff->setc(this,cc);
		else this->fa = ff;
		f->push_up();
	}
	inline Node* splay(){
		go();
		while(!isroot()){
			if(!fa->isroot())
				d()==fa->d() ? fa->rot() : rot();
			rot();
		}
		push_up();
		return this;
	}
	inline Node* access(){
		for(Node *p = this,*q = null; p != null; q = p, p = p->fa){
			p->splay()->setc(q,1);
			p->push_up();
		}
		return splay();
	}
	inline Node* find_root(){
		Node *x;
		for(x = access(); x->push_down(), x->ch[0] != null; x = x->ch[0]);
		return x;
	}
	void make_root(){
		access()->flip();
	}
	void cut(){
		access();
		ch[0]->fa = null;
		ch[0] = null;
		push_up();
	}
	void cut(Node *x){    //删除该节点和x之间的边。
		if(this == x || find_root() != x->find_root())return;
		else{
			x->make_root();
			cut();
		}
	}
	void link(Node *x){    //该节点链接x节点。(即该节点和x节点之间加一条边)
		if(find_root() == x->find_root())return;
		else {
			make_root(); fa = x;
		}
	}
};
int read()  //读入优化
{
    int ans = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9'){
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans;
}
Node pool[MAXN],*tail;
Node *node[MAXN];
struct Edge{
	int to,next;
}edge[MAXN*2];
int head[MAXN],tot;
void init(){
	tot = 0;
	memset(head,-1,sizeof(head));
}
inline void addedge(int u,int v){
	edge[tot].to = v;
	edge[tot].next = head[u];
	head[u] = tot++;
}
int g[MAXN];
int fa[MAXN];
void bfs(int s){  //用来建树
	int l,r;
	g[l=r=1] = s;
	fa[s] = s;
	while(l <= r){
		int u = g[l++];
		for(int i = head[u];i != -1;i = edge[i].next){
			int v = edge[i].to;
			if(v == fa[u])continue;
			fa[v] = u;
			node[v]->fa = node[u];
			g[++r] = v;
		}
	}
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
	int T;
	int n,m;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		tail = pool;
		null = tail++;
		null->fa = null->ch[0] = null->ch[1] = null;
		null->Max = -INF;
		null->Min = INF;
		null->mm = 0;
		null->add = null->rev = 0;
		for(int i = 1;i <= n;i++){
			int v ;
			//scanf("%d",&v);  //初始化点权
			v=read();
			node[i] = tail++;
			node[i]->clear(v);
		}
		init();
		int u,v;
		for(int i = 1;i < n;i++){
			scanf("%d%d",&u,&v); 
			addedge(u,v);  //这里本来可以直接用node[u]->link(node[v]);来直接建边的,但是会慢一点,本题会TLE。
			addedge(v,u);
		}
		bfs(1);//前面一个循环先输入边,dfs用来建树。这样会比每次输一个边就建一条边快好多(本题卡时间就这样做)。
		int w;
		scanf("%d",&m);
		while(m--){
			//scanf("%d%d%d",&u,&v,&w);
			u=read();
			v=read();
			w=read();
			node[u]->make_root();
			node[v]->access();
			printf("%d\n",node[v]->mm);
			node[v]->update_add(w);
		}
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值