spoj6779 Can you answer these queries VII(gss7)动态树

 看了一下题,二话没说,想拍一个树链剖分,像线段树维护一下4个值就行了,可是想想树链剖分那长长的代码,额~(⊙o⊙)…  

突然想到一句话,一切尽动态树。  

先把建立一颗树吧 ,这里用1作为根, 这样的话这棵树就已经定型了。 刚开始每个节点只记录双亲。 这样任意两个节点 向着根所走过的路  要吗在路中间有交点,要么在根上有交点,要么就直接交与这两个点的某一个点了。利用这个性质我们可以yy很多东西呀~~~

#define fi freopen("in.txt","r",stdin)
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define sfint(x) scanf("%d",&x)
#define sfint2(x,y) scanf("%d%d",&x,&y)
#define sfint3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sfstr(c) scanf("%s",c)
#define pfint(x) printf("%d\n",x)
#define fr(i,s,n) for(i=s;i<n;++i)
#define _fr(i,n,s) for(i=n-1;i>=s;--i)
#define cl(a) memset(a,0,sizeof(a))
const int NMax =100100;
const int M = 200010;
struct Edg
{
	int u,v,nxt; 
}edg[M];	
int tote,head[NMax];
int num;
void init(){
	tote = 0;
	memset(head,-1,sizeof(head));
}
inline void addedg(int u,int v){
	edg[tote].u=u;edg[tote].v=v;edg[tote].nxt=head[u];head[u]=tote++;
};

struct node
{
	int val,mx,lmx,rmx,sum,siz;
	bool chg;
	node *l,*r,*f;
	void Chg(int x){
		chg = 1;
		val = x;
		sum = x*siz;
		mx = lmx = rmx = (x > 0) ? sum : 0;
	}
	void down();
	void update() 	{ 
		siz = l->siz + r->siz +1;
		sum = l->sum + r->sum + val;
		mx = max(max(l->mx,r->mx),l->rmx+r->lmx+val);
		lmx = max(l->lmx,l->sum+val+r->lmx);
		rmx = max(r->rmx,r->sum+val+l->rmx);
	}
} nodes[NMax],*nil=nodes;
int n,m;

void node::down(){
	if (chg){
		if (l!=nil) l->Chg(val);
		if (r!=nil) r->Chg(val);
		chg = 0;
	}
}
class Lct
{
public:
	void zig(node *p)
	{
		node *q=p->f,*y=q->f;
		q->down();p->down();
		if ((q->l=p->r))q->l->f=q;
		p->r=q;
		q->f=p;
		p->f=y;
		if (y!=nil)
		{
			if (y->l==q)y->l=p;
			else if (y->r==q)y->r=p;
		}
		q->update();
	}
	void zag(node *p)
	{	
		node *q=p->f,*y=q->f;
		q->down(); p->down();  
		if ((q->r=p->l))q->r->f=q;
		p->l=q;
		q->f=p;
		p->f=y;
		if (y!=nil)
		{
			if (y->l==q)y->l=p;
			else if (y->r==q)y->r=p;
		}
		q->update();
	}
	void Splay(node *p)
	{
		p->down();
		while ((p->f)!=nil && (p->f->l==p || p->f->r==p))
		{
			node *q=p->f,*y=q->f;
			if (y!=nil && y->l==q)
			{
				if (q->l==p)zig(q),zig(p);
				else zag(p),zig(p);
			}
			else if (y!=nil && y->r==q)
			{
				if (q->r==p)zag(q),zag(p);
				else zig(p),zag(p);
			}
			else
			{
				if (q->l==p)zig(p);
				else zag(p);
			}
		}
		p->update();
	}
	node *Expose(node *p){
		node *q;
		for (q=nil; p!=nil; p=p->f){
			Splay(p);
			p->r=q;
			(q=p)->update();
		}
		return q;
	}
	void change(int x,int y,int c){
		node *p=nodes+x,*q=nodes+y;
		Expose(p);
		node * root;
		for(root = nil; q!=nil; q=q->f){
			Splay(q);
			if (q->f==nil) {
				q->r->Chg(c);root->Chg(c);q->val = c;
			}
			q->r = root;
			root = q;
			root->update();
		}
	}
	int Ask(int x,int y)    {
		node *p=nodes+x,*q=nodes+y;
		Expose(p);
		node * root;
		for(root = nil; q!=nil; q=q->f){
			Splay(q);
			if (q->f==nil) {
				int ans = max(q->r->mx,root->mx);
				ans = max(ans,q->r->lmx+root->lmx+q->val);
				return ans;
			}e
			q->r = root;
			root = q;
			root->update();
		}
	}
}lct;
int q[NMax];
void bfs(){
	int f=0,r=1,i,u,v;
	q[0] = 1;
	for (i=0;i<=n;i++)nodes[i].f=nil;
	while(f!=r){
		u = q[f++];
		for(i = head[u];i!=-1;i=edg[i].nxt){
			v = edg[i].v;
			if (v!=1 && nodes[v].f == nil){
				nodes[v].f=nodes+u;
				q[r++] = v;
			}
		}
	}
}
void make_map(){
	int i,u,v;
	sfint(n);
	fr(i , 1,n+1){
		sfint(num);
		nodes[i].siz =1;
		nodes[i].val = nodes[i].sum = nodes[i].mx = nodes[i].lmx = nodes[i].rmx = num;
		nodes[i].l = nodes[i].r = nil;
	}
	init();
	fr(i,0,n-1){
		sfint2(u,v);
		addedg(u,v);
		addedg(v,u);
	}
	bfs();
}

void solve(){
	int i,op,u,v,w;
	sfint(m);
	fr(i,0,m){
		sfint(op);
		if (op ==1){
			sfint2(u,v);
			pfint(lct.Ask(u,v));
		}
		else{
			sfint3(u,v,w);
			lct.change(u,v,w);
		}
	}
}

int main()
{
#ifdef loca
	fi;
#endif
	nil->siz = 0;nil->l = nil->r = nil;nil->mx = nil->lmx=nil->rmx = nil->val = 0;
	make_map();
	solve();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值