【BZOJ 1180】[CROATIAN2009]OTOCI LCT

236 篇文章 0 订阅
6 篇文章 0 订阅

第一次只用30分钟写完然后1A有点激动,虽然是一道很裸很傻逼的LCT啦

#include<cstdio>
#include<cstring>
#include<iostream>
#define ls(u) ch[u][0]
#define rs(u) ch[u][1]
#define maxn 300021
using namespace std;
int n,m,ch[maxn][2],sum[maxn],q[maxn],flag[maxn],top,fa[maxn],val[maxn];

inline int Q(int u){return u==rs(fa[u]);}
inline int isrt(int u){return !fa[u]||(u!=ls(fa[u])&&u!=rs(fa[u]));}
inline void push_up(int u){sum[u]=sum[ls(u)]+sum[rs(u)]+val[u];}
inline void push_down(int u){
	swap(ls(u),rs(u));flag[u]=0;
	if(ls(u))flag[ls(u)]^=1;
	if(rs(u))flag[rs(u)]^=1;
}
void rotate(int u){
	int d=!Q(u),f=fa[u];
	if(!isrt(f))ch[fa[f]][Q(f)]=u;fa[u]=fa[f];
	if(ch[u][d])fa[ch[u][d]]=f;ch[f][!d]=ch[u][d];
	fa[f]=u;ch[u][d]=f;
	push_up(f);push_up(u);
}
void splay(int u){
	q[top=1]=u;
	for(int i=u;!isrt(i);i=fa[i])q[++top]=fa[i];
	for(int i=top;i>=1;i--)if(flag[q[i]])push_down(q[i]);
	while(!isrt(u)){
		if(isrt(fa[u]))rotate(u);
		else {
			if(Q(u)==Q(fa[u]))rotate(fa[u]);
			else rotate(u);
			rotate(u);
		}
	}
}
void access(int u){
	for(int x=0;u;u=fa[x=u]){
		splay(u);rs(u)=x;push_up(u);
	}
}
void makert(int u){
	access(u);splay(u);flag[u]^=1;
}
void link(int a,int b){
	makert(a);fa[a]=b;
}
bool isuni(int a,int b){
	makert(a);access(b);splay(b);
	while(ls(b))b=ls(b);
	return b==a;
}
void update(int u,int x){
	access(u);splay(u);val[u]=x;
	push_up(u);
}
void query(int a,int b){
	if(!isuni(a,b))puts("impossible");
	else printf("%d\n",sum[b]);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",val+i);
	scanf("%d",&m);int a,b;char s[15];
	while(m--){
		scanf("%s%d%d",s,&a,&b);
		if(s[0]=='b'){
			if(!isuni(a,b))link(a,b),puts("yes");
			else puts("no");
		}else if(s[0]=='p'){
			update(a,b);
		}else query(a,b);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值