LG P1505 [国家集训队]旅游(LCT维护花里胡哨的标记)

130 篇文章 1 订阅
124 篇文章 0 订阅

题目

每日一板。
注意pushdown需要到子节点。
比树剖慢6倍。

AC Code:

#include<bits/stdc++.h>
#define maxn 40005
#define inf 0x3f3f3f3f
using namespace std;

int n,m;
int tot;
namespace LCT{
	int fa[maxn],ch[maxn][2],sum[maxn],val[maxn],Max[maxn],Min[maxn];
	int rev[maxn],neg[maxn];
	#define il inline 
	#define pa fa[x]
	il int inr(int x){ return ch[pa][1]==x; }
	il int isr(int x){ return ch[pa][0]!=x && ch[pa][1]!=x;} 
	il void dtp(int x){
		val[x] = -val[x];
		sum[x] = -sum[x];
		swap(Max[x],Min[x]);
		Max[x] = -Max[x];
		Min[x] = -Min[x];
		neg[x] ^= 1;
	}
	il void dt(int x){
		if(rev[x]){
			swap(ch[x][0],ch[x][1]),rev[x]=0;
			if(ch[x][0]) rev[ch[x][0]] ^= 1;
			if(ch[x][1]) rev[ch[x][1]] ^= 1;
		}
		if(neg[x]){
			if(ch[x][0]) dtp(ch[x][0]);
			if(ch[x][1]) dtp(ch[x][1]);
			neg[x] = 0;
		}
	}
	il void dtpath(int x){
	//printf("%d %d %d\n",x,isr(x),fa[x]);	
		if(!isr(x)) dtpath(pa); dt(x); }
	il void upd(int x){
		sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + val[x];
		Max[x] = (x<=n ? -inf : val[x]);
		Min[x] = (x<=n ? inf : val[x]);
		if(ch[x][0]) Max[x] = max(Max[x] , Max[ch[x][0]]) , Min[x] = min(Min[x],Min[ch[x][0]]);
		if(ch[x][1]) Max[x] = max(Max[x] , Max[ch[x][1]]) , Min[x] = min(Min[x],Min[ch[x][1]]);
	}
	il void rot(int x){
		int y = fa[x] , z = fa[y] , c = inr(x);
		if(!isr(y)) ch[z][inr(y)] = x;
		(ch[y][c]=ch[x][!c])&&(fa[ch[y][c]]=y);
		fa[fa[ch[x][!c]=y]=x]=z;
		upd(y),upd(x);
	}
	il void splay(int x){
		for(dtpath(x);!isr(x);rot(x))
			if(!isr(pa)) rot(inr(pa) == inr(x) ? pa : x);
	}
	il int access(int x,int y=0){
		for(;x;x=fa[y=x]) splay(x),ch[x][1]=y,upd(x);
		return y;
	}
	il void bert(int x){
		access(x),splay(x),rev[x]^=1;
	}
	il int split(int x,int y){
		bert(x),access(y),splay(y);
		return y;
	}
	il void link(int x,int y){
		bert(x),fa[x]=y;
	}
	il void addneg(int x,int y){
		split(x,y);
		dtp(y);
	}
	il int qsum(int u,int v){ return sum[split(u,v)]; } 
	il int qmax(int u,int v){ return Max[split(u,v)]; } 
	il int qmin(int u,int v){ return Min[split(u,v)]; } 
}

using namespace LCT;

int main(){
	//freopen("1.out","w",stdout);
	scanf("%d",&n);tot = n;
	for(int i=1,u,v,w;i<n;i++){
		scanf("%d%d%d",&u,&v,&w);u++,v++;
		val[++tot] = w , upd(tot);
		link(u,tot),link(tot,v);
	}
	scanf("%d",&m);
	char s[10];
	for(int i=1,u,v;i<=m;i++){
		scanf("%s%d%d",s,&u,&v);u++,v++;
		if(s[0] == 'C')
		{
			v--,u--;
			splay(u+n);
			val[u+n]=v;
			upd(u+n);
		}
		if(s[0] == 'N') addneg(u,v);
		if(s[0] == 'S') printf("%d\n",qsum(u,v));
		if(s[0] == 'M' && s[1] == 'I') printf("%d\n",qmin(u,v));
		if(s[0] == 'M' && s[1] == 'A') printf("%d\n",qmax(u,v));
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值