【洛谷 P3391】 文艺平衡树 【平衡树】

本文介绍了如何使用fhqTreap数据结构来解决洛谷P3391问题,通过线段树懒标记处理区间翻转,并详细讲解了split、make和K等关键操作,展示了如何在实际场景中应用这种数据结构进行动态区间操作。

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

【洛谷 P3391】 文艺平衡树

题目大意:

写一种数据结构支持静态区间的翻转操作。

思路:

考虑使用线段树中的懒标记,每次区间发生变化时遇到懒标记就下传。
每次下传时懒标记 x o r   1 xor ~1 xor 1,就是如果没有懒标记那么就打上,如果以前有的话那么说明这个区间翻转了两次,和没翻转一样。
使用平衡树 fhq Treap 解决。
注意分裂的时候不是按照权值分裂了,而是前 k 个。
所谓的模板题

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#include<ctime>
#define r register
#define rep(i,x,y) for(r ll i=x;i<=y;++i)
#define per(i,x,y) for(r ll i=x;i>=y;--i)
using namespace std;
typedef long long ll;
const ll V=1e5+10;
ll a[V],n,m,q,root,cnt;
ll u,v,x,y,z;
inline ll in()
{
	ll res=0,f=1;
	char ch;
	while((ch=getchar())<'0'||ch>'9')
	 if(ch=='-') f=-1;
	res=res*10+ch-48;
	while((ch=getchar())>='0'&&ch<='9')
	 res=res*10+ch-48;
	return res*f;
}
inline void put(ll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) put(x/10);
	putchar(x%10+48);
}
struct fhqtreap
{
	ll lc,rc,pos;
	ll siz,val,lazy;
}treap[110003];
void update(ll x) { treap[x].siz=treap[treap[x].lc].siz+treap[treap[x].rc].siz+1; }
ll newnode(ll x) 
{
	treap[++cnt].val=x;
	treap[cnt].siz=1;
	treap[cnt].pos=rand();
	return cnt;
}
void pushdown(ll x) //懒标记的下传
{
	swap(treap[x].lc,treap[x].rc);
	treap[treap[x].lc].lazy^=1;
	treap[treap[x].rc].lazy^=1;
	treap[x].lazy=0;
}
void split(ll now,ll k,ll &x,ll &y)
{
	if(now==0)
	{
		x=y=0;
		return ;
	}
	if(treap[now].lazy) pushdown(now);
	if(k>=treap[treap[now].lc].siz+1)
	{
		x=now;
		split(treap[now].rc,k-treap[treap[now].lc].siz-1,treap[now].rc,y);
	}
	else 
	{
		y=now;
		split(treap[now].lc,k,x,treap[now].lc);
	}
	update(now);
}
ll make(ll x,ll y)
{
	if(x==0||y==0) return x+y;
	if(treap[x].pos<treap[y].pos)
	{
		if(treap[x].lazy) pushdown(x); //记得及时下传懒标记
		treap[x].rc=make(treap[x].rc,y);
		update(x);
		return x;
	}
	else 
	{
		if(treap[y].lazy) pushdown(y);
		treap[y].lc=make(x,treap[y].lc);
		update(y);
		return y;
	}
}
ll K(ll now,ll k)
{
	while(1+1==2)
	{
		if(k<=treap[treap[now].lc].siz) now=treap[now].lc;
		else if(k==treap[treap[now].lc].siz+1) return now;
		else k-=(treap[treap[now].lc].siz+1),now=treap[now].rc;
	}
}
void print(ll now) //中序遍历输出答案
{
	if(now==0) return ;
	if(treap[now].lazy) pushdown(now);
	if(treap[now].lc) print(treap[now].lc);
	printf("%lld ",treap[now].val);
	if(treap[now].rc) print(treap[now].rc);
}
int main()
{
	n=in(),m=in();
	rep(i,1,n)
	 root=make(root,newnode(i));
	rep(i,1,m)
	{
		
		u=in(),v=in();
		split(root,v,x,z);//1~v->x,v+1->z
		split(x,u-1,x,y);//1~u-1->x,u~v->y
		treap[y].lazy^=1;
		root=make(make(x,y),z);
	}
	print(root);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值