项链工厂 - 平衡树

31 篇文章 1 订阅

题面

 题解

一道平衡树的复杂细节题。我用的非旋Treap

R k     把整棵树从中间n - k - 1后面分开,再倒转顺序合并

F        把2~n翻转过来,用懒标记

S i j    使i < j 相当于revolve(i,j,1) , revolve(i+1,j,j - i - 1)

P i j x 还是用懒标记,j可能小于i

C        查询root,要判首尾。

CS i j  查询一段,不判首尾,j可能小于i。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define LL long long
#define MAXN 500000 + 5
using namespace std;
inline LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
	return x * f;
}
LL n,m,i,j,s,o,k,cnt,root,root2,MINN;
bool flag = 0;
struct npair{
	LL p[2];
	npair(){p[0] = p[1] = 0;}
	npair(LL l,LL r){p[0] = l;p[1] = r;}
};
struct tr{
	LL s[2],fa;
	LL key;
	LL heap,siz,lz,me,la,ra,a,lzc;
	tr(){key = 0;s[0] = s[1] = 0;heap = 0;siz = 0;lz = 0;me = 0;la = ra = a = 0;fa = 0;lzc = 0;}
}tre[MAXN];
int newnode(int nm) {
	tre[++cnt] = tr();
	tre[cnt].me = nm;
	tre[cnt].a = 1;
	tre[cnt].la = nm;
	tre[cnt].ra = nm;
	tre[cnt].heap = unsigned(rand()) + 1;
	tre[cnt].siz = 1;
	return cnt;
}
void update(int x) {
	tre[0] = tr();
	if(x == 0) return ;
	tre[x].siz = 1 + tre[tre[x].s[0]].siz + tre[tre[x].s[1]].siz;
	int l = tre[x].s[0],r = tre[x].s[1];
	if(tre[x].lzc) {
		tre[x].a = 1;
		tre[x].ra = tre[x].la = tre[x].me;
	}
	else {
		int c1 = (tre[x].lz ? tre[l].ra:tre[l].la);
		int c2 = (tre[x].lz ? tre[l].la:tre[l].ra);
		int c3 = (tre[x].lz ? tre[r].ra:tre[r].la);
		int c4 = (tre[x].lz ? tre[r].la:tre[r].ra);
		tre[x].a = 1 + tre[l].a + tre[r].a - (c2 == tre[x].me ? 1:0) - (tre[x].me == c3 ? 1:0);
		tre[x].la = (c1 == 0 ? tre[x].me:c1);
		tre[x].ra = (c4 == 0 ? tre[x].me:c4);
	}
	tre[l].fa = tre[r].fa = x;
}
void change(int x) {
	if(x) {
		tre[x].lz ^= 1;
		swap(tre[x].s[0],tre[x].s[1]);
		update(x);
	}
}
void modify(int x,int cl) {
	if(x) {
		tre[x].lzc = 1;
		tre[x].me = cl;
		tre[x].a = 1;
		tre[x].la = cl;
		tre[x].ra = cl;
	}
}
void pushdown(int x) {
	if(tre[x].lz) {
		tre[x].lz = 0;
		change(tre[x].s[0]);
		change(tre[x].s[1]);
	}
	if(tre[x].lzc) {
		tre[x].lzc = 0;
		modify(tre[x].s[0],tre[x].me);
		modify(tre[x].s[1],tre[x].me);
	}
}
npair spli(int x,int m) {
	npair as;
	if(x == 0) return as;
	int d = (tre[tre[x].s[0]].siz + 1 <= m);
	pushdown(x);
	if(d) as = spli(tre[x].s[1],m - tre[tre[x].s[0]].siz - 1);
	else as = spli(tre[x].s[0],m);
	tre[x].s[d] = as.p[d^1];
	update(x);
	as.p[d^1] = x;
	return as;
}
int merg(int p1,int p2) {
	if(!p1) return p2;
	if(!p2) return p1;
	if(tre[p1].heap < tre[p2].heap) {
		pushdown(p1);
		tre[p1].s[1] = merg(tre[p1].s[1],p2);
		update(p1);
		return p1;
	}
	else {
		pushdown(p2);
		tre[p2].s[0] = merg(p1,tre[p2].s[0]);
		update(p2);
		return p2;
	}
}
int supersplay(int x,int ml,int mr) {
	npair f1 = spli(x,mr);
	npair f2 = spli(f1.p[0],ml - 1);
	change(f2.p[1]);
	return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int ins(int x,int m,int nm) {
	npair f1 = spli(x,m);
	return merg(merg(f1.p[0],newnode(nm)),f1.p[1]);
}
int del(int x,int m) {
	npair f1 = spli(x,m);
	npair f2 = spli(f1.p[0],m - 1);
	return merg(f2.p[0],f1.p[1]);
}
int idp(int &x,int m) {
	npair f1 = spli(x,m);
	npair f2 = spli(f1.p[0],m - 1);
	int as = f2.p[1];
	x = merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
	return as;
}
int rerun(int x,int t) {
	int n = tre[x].siz;t = (t - 1) % n + 1;
	npair f1 = spli(x,n - t);
	return merg(f1.p[1],f1.p[0]);
}
int partrun(int x,int l,int r,int t) {
	npair f1 = spli(x,r);
	npair f2 = spli(f1.p[0],l - 1);
	f2.p[1] = rerun(f2.p[1],t);
	return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int addk(int x,int l,int r,int cl) {
	npair f1 = spli(x,r);
	npair f2 = spli(f1.p[0],l - 1);
	modify(f2.p[1],cl);
	return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int addoutk(int x,int l,int r,int cl) {
	npair f1 = spli(x,r);
	npair f2 = spli(f1.p[0],l - 1);
	modify(f1.p[1],cl);
	modify(f2.p[0],cl);
	return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int getmin(int x,int l,int r) {
	npair f1 = spli(x,r);
	npair f2 = spli(f1.p[0],l - 1);
	MINN = tre[f2.p[1]].a;
	return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int getoutmin(int x,int l,int r) {
	npair f1 = spli(x,r);
	npair f2 = spli(f1.p[0],l - 1);
	MINN = tre[f1.p[1]].a + tre[f2.p[0]].a - (tre[f1.p[1]].ra == tre[f2.p[0]].la ? 1:0);
	return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
void print(int x) {
	if(x == 0) return ;
	pushdown(x);
	print(tre[x].s[0]);
	printf("%d(%d,%d)[a:%d c:%d l:%d r:%d] ",x,tre[x].s[0],tre[x].s[1],tre[x].a,tre[x].me,tre[x].la,tre[x].ra);
	print(tre[x].s[1]);
	update(x);
}
int main() {
	n = read();m = read();
	for(int i = 1;i <= n;i ++) {
		root = ins(root,i - 1,read());
	}
	int T = read();
	char ss[10];
	while(T --) {
		scanf("%s",ss + 1);
//		cout<<"ok"<<endl;
		if(ss[1] == 'R') {
			k = read();
			root = rerun(root,k);
		}
		else if(ss[1] == 'F') {
			root = supersplay(root,2,n);
		}
		else if(ss[1] == 'S') {
			s = read();o = read();
			if(s > o) swap(s,o);
			if(s != o)
				root = partrun(root,s,o,1),root = partrun(root,s + 1,o,o - s - 1);
		}
		else if(ss[1] == 'P') {
			s = read();o = read();k = read();
			if(s <= o)root = addk(root,s,o,k);
			else root = addoutk(root,o + 1,s - 1,k);
		}
		else if(ss[1] == 'C' && ss[2] == 'S') {
			s = read();o = read();
			if(s > o) {
				root = getoutmin(root,o + 1,s - 1);
			}
			else root = getmin(root,s,o);
			printf("%d\n",MINN); 
		}
		else if(ss[1] == 'C') {
			MINN = tre[root].a;
			printf("%d\n",MINN - (tre[root].la == tre[root].ra && MINN > 1 ? 1:0));
		}
		else if(ss[1] == 'D') {
			print(root);putchar('\n');
		}
		
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值