NOIp训练 [SCOI2018]Tree(链分治)

传送门
题意:
给一棵带点权的树,要求支持如下操作:

  1. 询问从 U 出发的简单路径,经过的点权值之和的最大值
  2. 将 U 的权值修改为 V

空间限制64MB


思路:
你可以使用一种叫做点分树的无脑方法,然后用 s h o r t + c h a r short+char short+char 3 4 \frac34 43 i n t int int可以通过这一道题。 毕竟毒瘤出题人卡了空间
你显然也可以上 l c t lct lct搞。博主懒癌晚期不想写/想了
实在不行的就学博主大力点分吧。
这跟那个 Q T R E E QTREE QTREE系列是一个套路,对于每条链用可删堆维护子树的信息,用线段树维护重链的信息,然后每次像上面跳即可。
注意这个时候查最大值直接跳可能会走到重复的点,因此查询的时候要先消除当前节点所在子树的影响才行。
代码:

#include
#define ri register int
using namespace std;
typedef long long ll;
inline int read(){
	int ans=0;
	bool f=1;
	char ch=getchar();
	while(!isdigit(ch))f^=ch=='-',ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return f?ans:-ans;
}
typedef long long ll;
const int N=1e5+5,inf=0x3f3f3f3f;
int n,pred[N],num[N],tot=0,m,a[N],dep[N],top[N],fa[N],hson[N],siz[N],bot[N];
vector<int>e[N];
void dfs1(int p){
	siz[p]=1;
	for(ri i=0,v;i<e[p].size();++i){
		dep[v=e[p][i]]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
		if(siz[v]>siz[hson[p]])hson[p]=v;
	}
}
void dfs2(int p,int tp){
	top[p]=tp,bot[tp]=p,pred[num[p]=++tot]=p;
	if(!hson[p])return;
	dfs2(hson[p],tp);
	for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i])!=hson[p])dfs2(v,v);
}
struct deletable_priority_queue{
	priority_queue<int>a,b;
	inline void push(const int&x){a.push(x);}
	inline void del(const int&x){b.push(x);}
	inline int top(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();return a.top();}
}S[N];
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (T[p].l+T[p].r>>1)
	struct Node{int l,r,ls,rs,sum;}T[N<<2];
	inline Node operator+(const Node&a,const Node&b){return (Node){a.l,b.r,max(a.ls,a.sum+b.ls),max(b.rs,b.sum+a.rs),a.sum+b.sum};}
	inline void Set(int p){
		int k=pred[T[p].l];
		T[p].sum=a[k],T[p].ls=T[p].rs=S[k].top()+a[k];
	}
	inline void pushup(int p){T[p]=T[lc]+T[rc];}
	inline void build(int p,int l,int r){
		T[p].l=l,T[p].r=r,T[p].sum=0,T[p].ls=T[p].rs=-inf;
		if(l==r)return;
		build(lc,l,mid),build(rc,mid+1,r);
	}
	inline void update(int p,int k){if(T[p].l==T[p].r)return Set(p);update(k<=mid?lc:rc,k),pushup(p);}
	inline Node query(int p,int ql,int qr){
		if(ql<=T[p].l&&T[p].r<=qr)return T[p];
		if(qr<=mid)return query(lc,ql,qr);
		if(ql>mid)return query(rc,ql,qr);
		return query(lc,ql,mid)+query(rc,mid+1,qr);
	}
	#undef lc
	#undef rc
	#undef mid
}
int dfs3(int tp){
	for(ri p=tp;p;p=hson[p]){
		for(ri i=0,v;i<e[p].size();++i){
			if((v=e[p][i])==hson[p])continue;
			S[p].push(dfs3(v));
		}
		SGT::update(1,num[p]);
	}
	return SGT::query(1,num[tp],num[bot[tp]]).ls;
}
inline void update(int p){
	int ft,tp,bt;
	SGT::Node tmp;
	while(p){
		tp=top[p],ft=fa[tp],bt=bot[tp];
		if(ft)tmp=SGT::query(1,num[tp],num[bt]),S[ft].del(tmp.ls);
		SGT::update(1,num[p]);
		if(ft)tmp=SGT::query(1,num[tp],num[bt]),S[ft].push(tmp.ls);
		p=ft;
	}
}
inline void Del(int p){
	int ft,tp,bt;
	SGT::Node tmp;
	tp=top[p],ft=fa[tp],bt=bot[tp];
	if(!ft)return;
	tmp=SGT::query(1,num[tp],num[bt]);
	S[ft].del(tmp.ls);
	p=ft;
	while(p){
		tp=top[p],ft=fa[tp],bt=bot[tp];
		if(ft){
			tmp=SGT::query(1,num[tp],num[bt]);
			S[ft].del(tmp.ls);
		}
		SGT::update(1,num[p]);
		p=ft;
	}	
}
inline void Ins(int p){
	int ft,tp,bt;
	SGT::Node tmp;
	tp=top[p],ft=fa[tp],bt=bot[tp];
	if(!ft)return;
	tmp=SGT::query(1,num[tp],num[bt]);
	S[ft].push(tmp.ls);
	p=ft;
	while(p){
		tp=top[p],ft=fa[tp],bt=bot[tp];
		SGT::update(1,num[p]);
		if(ft){
			tmp=SGT::query(1,num[tp],num[bt]);
			S[ft].push(tmp.ls);
		}
		p=ft;
	}	
}
inline int query(int x){
	int ft,tp,bt,p=x,ret=SGT::query(1,num[x],num[bot[top[x]]]).ls,det=0;
	SGT::Node tmp;
	while(p){
		tp=top[p],ft=fa[tp],bt=bot[tp];
		tmp=SGT::query(1,num[tp],num[p]);
		ret=max(ret,tmp.rs+det);
		ret=max(ret,SGT::query(1,num[p],num[bt]).ls+det);
		det+=tmp.sum;
		p=ft;
	}
	return ret;
}
int main(){
	n=read(),m=read();
	for(ri i=2;i<=n;++i)fa[i]=read(),e[fa[i]].push_back(i);
	for(ri i=1;i<=n;++i)a[i]=read(),S[i].push(0);
	dfs1(1),dfs2(1,1),SGT::build(1,1,n),dfs3(1);
	for(ri op,x;m;--m){
		op=read(),x=read();
		if(op==1){
			Del(x);
			cout<<query(x)<<'\n';
			Ins(x);
		}
		else a[x]=read(),update(x);
	}
	return 0;
}

你可能感兴趣的:(#,线段树,#,树链剖分)