【BZOJ】【P2631】【tree】【题解】【LCT】

本文介绍了一种裸题,使用了线段树(LCT)数据结构进行优化,通过一系列的操作来解决实际问题,展示了数据结构在解决复杂问题时的高效性和实用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2631

裸题

Code:

#include<bits/stdc++.h>
#define id(x) (LCT::pool+x)
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
int mo=51061,n,m;
namespace LCT{
	struct node{
		int rev,val,mul,add,size,sum;
		node *c[2],*p;
		void makerev(){rev^=1;swap(c[0],c[1]);}
		void pd(){
			if(rev){rev=0;c[0]->makerev();c[1]->makerev();}
			if(mul==1&&!add)return;
			c[0]->val=((LL)c[0]->val*mul%mo+add)%mo;
			c[0]->sum=((LL)c[0]->sum*mul%mo+(LL)c[0]->size*add%mo)%mo;
			c[0]->mul=((LL)c[0]->mul*mul%mo)%mo;
			c[0]->add=((LL)c[0]->add*mul%mo+add)%mo;
			c[1]->val=((LL)c[1]->val*mul%mo+add)%mo;
			c[1]->sum=((LL)c[1]->sum*mul%mo+(LL)c[1]->size*add%mo)%mo;
			c[1]->mul=((LL)c[1]->mul*mul%mo)%mo;
			c[1]->add=((LL)c[1]->add*mul%mo+add)%mo;
			mul=1;add=0;
		}
		void rz(){
			sum=(c[0]->sum+val+c[1]->sum)%mo;
			size=c[0]->size+1+c[1]->size;
		}
		void sets(node *x,int d){pd();(c[d]=x)->p=this;rz();}
		bool d(){return p->c[1]==this;}
		bool rt(){return p->c[0]!=this&&p->c[1]!=this;}
	}*null,pool[maxn];
	node *newnode(int _val=0){
		static node *x=pool;
		x->rev=0;x->val=x->sum=_val;
		x->mul=1;x->add=0;x->size=1;
		x->c[0]=x->c[1]=x->p=null;
		return x++;
	}
	void init(){
		null=newnode();null->mul=0;null->size=0;
		null->c[0]=null->c[1]=null->p=null;
		for(int i=1;i<=n;i++)newnode(1);
	}
	void rot(node *x){
		node *y=x->p;if(!y->rt())y->p->pd();
		y->pd();x->pd();int d=x->d();
		y->sets(x->c[!d],d);
		if(y->rt())x->p=y->p;
		else y->p->sets(x,y->d());
		x->sets(y,!d);
	}
	void splay(node *x){
		for(;!x->rt();rot(x))if(x->p->rt());
		else if(x->d()==x->p->d())rot(x->p);
		else rot(x);
	}
	node *access(node *x){
		node *y=null;
		for(;x!=null;x=x->p)splay(x),x->sets(y,1),y=x;
		return y;
	}
	void makert(node *x){
		access(x)->makerev();splay(x);
	}
	node *findrt(node *x){
		for(x=access(x);x->pd(),x->c[0]!=null;x=x->c[0]);return x;
	}
	void link(node *x,node *y){
		makert(x);x->p=y;access(x);
	}
	void cut(node *x,node *y){
		makert(x);access(y);splay(y);
		y->c[0]=x->p=null;y->rz();
	}
	int Qsum(node *x,node *y){
		makert(x);access(y);splay(y);
		return y->sum;
	}
	void add(node *x,node *y,int c){
		makert(x);access(y);splay(y);
		y->val=(y->val+c)%mo;
		y->sum=(y->sum+(LL)y->size*c%mo)%mo;
		y->add=(y->add+c)%mo;		
	}
	void mul(node *x,node *y,int c){
		makert(x);access(y);splay(y);
		y->val=((LL)y->val*c)%mo;
		y->sum=((LL)y->sum*c)%mo;
		y->mul=((LL)y->mul*c)%mo;
		y->add=((LL)y->add*c)%mo;		
	}
}
int main(){
	scanf("%d%d",&n,&m);
	LCT::init();	
	for(int i=1;i<n;i++){
		int u,v;scanf("%d%d",&u,&v);
		LCT::link(id(u),id(v));
	}
	while(m--){
		char op=getchar();
		while(op!='+'&&op!='-'&&op!='*'&&op!='/')op=getchar();
		if(op=='+'){
			int u,v,c;scanf("%d%d%d",&u,&v,&c);
			LCT::add(id(u),id(v),c%mo);
		}else
		if(op=='-'){
			int u1,v1,u2,v2;scanf("%d%d%d%d",&u1,&v1,&u2,&v2);
			LCT::cut(id(u1),id(v1));
			LCT::link(id(u2),id(v2));
		}else
		if(op=='*'){
			int u,v,c;scanf("%d%d%d",&u,&v,&c);
			LCT::mul(id(u),id(v),c%mo);		
		}else
		if(op=='/'){
			int u,v;scanf("%d%d",&u,&v);
			printf("%d\n",LCT::Qsum(id(u),id(v)));
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值