1. 程式人生 > 其它 >[NOI2005] 維護數列

[NOI2005] 維護數列

成功從不會平衡樹的蒟蒻變成了會平衡樹的蒟蒻。

前言

這篇部落格是 \(\rm FHQ\ Treap\)

說句閒話,研究平衡樹的最好方法是:A了這道題,祝你們成功(滑稽

題目

洛谷

黑暗爆炸OJ

講解

沒什麼好說的,只是過了這道題很爽,想水一下部落格慶祝慶祝。

所有操作都是模板,確實沒什麼好講的,就講幾個細節吧。

  • 記得回收空間。

  • Reverse 操作的時候除了交換左右兒子,還要記得交換左右最大子段和。

  • 最大子段和不能為空集。

  • 更新最大子段和的時候很有可能會用到 \(0\) 號點,所以要把 \(0\) 號點與最大子段和相關的東西賦值為 \(-\infty\)

  • 插入的時候先把插入的點建成一棵很平衡的樹再插入,這樣不開 \(O2\)

    才能過。

程式碼

大常數程式碼
//12252024832524
#include <cstdio>
#include <cstring>
#include <algorithm>
#define TT template<typename T>
using namespace std; 

typedef long long LL;
const int MAXN = 500005;
const int MOD = 1e9 + 7;
int n,m;
char opt[10];

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

int rt;
struct FHQ_Treap
{
	int l,r,val,siz,s,rd;//左右兒子、權值、siz、區間和、om value 
	int lz1;//區間賦值標記 
	int lz2;//翻轉標記 
	int lm,rm,ms;//左右及全域性最大子段和
}t[MAXN];
int q[MAXN],tl = 500000;
unsigned long long lst = 233;
int Rand()
{
	lst *= 20050525;
	lst += 520123;
	return (int)(lst % MOD);
}
int newnode(int val)
{
	int ret = q[tl--];
	if(t[ret].l) q[++tl] = t[ret].l;
	if(t[ret].r) q[++tl] = t[ret].r;
	t[ret].lz1 = MOD;
	t[ret].lz2 = t[ret].l = t[ret].r = 0;
	t[ret].siz = 1;
	t[ret].lm = t[ret].rm = t[ret].ms = t[ret].s = t[ret].val = val;
	t[ret].rd = Rand();
	return ret;
}
void rev(int x)
{
	if(!x) return;
	t[x].lz2 ^= 1;
	swap(t[x].l,t[x].r);
	swap(t[x].lm,t[x].rm);
}
void fuzhi(int x,int val)
{
	if(!x) return;
	t[x].lz1 = val;
	t[x].s = t[x].siz * val;
	t[x].val = val;
	t[x].lm = t[x].rm = t[x].ms = Max(val,t[x].s);
}
void down(int x)
{
	if(t[x].lz1^MOD) fuzhi(t[x].l,t[x].lz1),fuzhi(t[x].r,t[x].lz1),t[x].lz1 = MOD;
	if(t[x].lz2) rev(t[x].l),rev(t[x].r),t[x].lz2 = 0;
}
void up(int x)
{
	t[x].siz = t[t[x].l].siz + t[t[x].r].siz + 1;
	t[x].s = t[t[x].l].s + t[t[x].r].s + t[x].val;
	t[x].lm = t[t[x].l].lm; t[x].lm = Max(t[x].lm,t[t[x].l].s + t[x].val + Max(0,t[t[x].r].lm));
	t[x].rm = t[t[x].r].rm; t[x].rm = Max(t[x].rm,t[t[x].r].s + t[x].val + Max(0,t[t[x].l].rm));
	t[x].ms = Max(t[t[x].l].ms,t[t[x].r].ms);
	t[x].ms = Max(t[x].ms,Max(t[x].lm,t[x].rm));
	t[x].ms = Max(t[x].ms,t[x].val+Max(0,t[t[x].l].rm)+Max(0,t[t[x].r].lm));
}
void split(int now,int val,int &x,int &y)
{
	if(!now) {x = y = 0;return;}
	down(now);
	if(t[t[now].l].siz+1 <= val)
	{
		x = now;
		split(t[now].r,val-t[t[now].l].siz-1,t[now].r,y);
	}
	else
	{
		y = now;
		split(t[now].l,val,x,t[now].l);
	}
	up(now); 
}
int mge(int x,int y)
{
	if(!x || !y) return x|y;
	if(t[x].rd < t[y].rd)
	{
		down(x);
		t[x].r = mge(t[x].r,y); up(x);
		return x;
	}
	else
	{
		down(y);
		t[y].l = mge(x,t[y].l); up(y);
		return y;
	}
}
void recycle(int x){q[++tl] = x;}
int a[MAXN];
int Build(int l,int r)
{
	if(l > r) return 0;
	int mid = (l+r) >> 1;
	int now = newnode(a[mid]);
	t[now].l = Build(l,mid-1);
	t[now].r = Build(mid+1,r);
	up(now);
	return now;
}

int main()
{
//	freopen("P2042_2.in","r",stdin);
//	freopen("mine.out","w",stdout);
	t[0].lm = t[0].rm = t[0].ms = -MOD;
	for(int i = 1;i <= tl;++ i) q[i] = i;
	n = Read(); m = Read();
	for(int i = 1;i <= n;++ i) rt = mge(rt,newnode(Read()));
	int x,y,z;
	while(m --> 0)
	{
		scanf("%s",opt);
		if(opt[0] == 'I')
		{
			int pos = Read(),len = Read();
			split(rt,pos,x,y);
			for(int i = 1;i <= len;++ i) a[i] = Read();
			rt = mge(mge(x,Build(1,len)),y);
		}
		else if(opt[0] == 'D')
		{
			int pos = Read(),len = Read();
			split(rt,pos-1,x,y);
			split(y,len,y,z);
			rt = mge(x,z);
			recycle(y);
		}
		else if(opt[2] == 'K')
		{
			int pos = Read(),len = Read();
			split(rt,pos-1,x,y);
			split(y,len,y,z);
			fuzhi(y,Read());
			rt = mge(mge(x,y),z);
		}
		else if(opt[0] == 'R')
		{
			int pos = Read(),len = Read();
			split(rt,pos-1,x,y);
			split(y,len,y,z);
			rev(y);
			rt = mge(mge(x,y),z);
		}
		else if(opt[0] == 'G')
		{
			int pos = Read(),len = Read();
			split(rt,pos-1,x,y);
			split(y,len,y,z);
			Put(t[y].s,'\n');
			rt = mge(mge(x,y),z);
		}
		else if(opt[2] == 'X') Put(t[rt].ms,'\n');
	}
	return 0;
}