【noi2005】维护数列

时隔半年我又来写这道题了,这次的Splay模版简练多了。有好多种操作,注意垃圾回收。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define RepE(i, x) for (int i = pos[x]; i; i = g[i].nex)
#define N 500005
#define u t[x]
#define lc t[x].ch[0]
#define rc t[x].ch[1]
#define Lc t[lc]
#define Rc t[rc]
#define Ts t[x].sum
#define tp t[x].par
#define Tp t[tp]
#define Tz t[x].lz

using namespace std;
typedef long long LL;
const int inf = 10000;
int n, m, sz, a[N], rt, b[N];
struct arr { 
	int ch[2], par, ml, mr, mx, sum, lz, num, v; bool rv;
	void Set(int x) { ml = mr = mx = ch[0] = ch[1] = par = sum = rv = 0, v = x, lz = inf; }
} t[N];
void PD(int x) {
	if (!x) return ;
	if (Tz != inf) {
		Lc.lz = Rc.lz = u.v = Tz;
		u.sum = Tz * u.num;
		u.mx = (Tz < 0) ? Tz : t[x].sum;
		u.ml = u.mr = max(0, u.mx);
		Tz = inf;
	}
	if (t[x].rv) {
		u.rv = 0, swap(lc, rc), Lc.rv ^= 1, Rc.rv ^= 1;
		swap(u.ml, u.mr);
	}
}
void Upd(int x) {
	if (!x) return ;
	PD(x), PD(lc), PD(rc);
	Ts = Lc.sum + Rc.sum + u.v;
	u.num = Lc.num + Rc.num + 1;
	u.ml = max(Lc.ml, Lc.sum + u.v + max(Rc.ml, 0));
	u.mr = max(Rc.mr, Rc.sum + u.v + max(Lc.mr, 0));
	u.mx = max(Lc.mx, max(Rc.mx, max(Lc.mr, 0) + u.v + max(0, Rc.ml)));
}
void Sc(int x, int y, bool f) { if (x) u.ch[f] = y; t[y].par = x; }
inline bool d(int x) { return Tp.ch[1] == x; }
void Rot(int x) {
	int y = tp, z = Tp.par, ty = d(x);
	Sc(z, x, d(y)), Sc(y, t[x].ch[!ty], ty), Sc(x, y, !ty), Upd(y);// Upd(x);
}
void Splay(int x, int z = 0) {
	PD(x); if (!z) rt = x;
	while (tp != z) {
		PD(tp), PD(x);
		if (Tp.par == z) { Rot(x); break ; }
		(d(x) == d(tp)) ? (Rot(tp), Rot(x)) : (Rot(x), Rot(x));
	} Upd(x);
}
int Build(int l, int r) {
	if (l > r) return 0;
	int x = b[++ sz];
	int mid = (l + r) >> 1;
	u.Set(a[mid]);
	lc = Build(l, mid-1), rc = Build(mid+1, r);
	Lc.par = Rc.par = x, Tz = inf, Upd(x);
	return x;
}
int Find(int x, int y) {
	PD(x);
	if (Lc.num + 1 < y) return Find(rc, y-(Lc.num+1));
	else if (Lc.num + 1 == y) return x;
	else return Find(lc, y);
}
int Get(int x, int y) {
	x ++, y ++;
	int x1 = Find(rt, x), x2 = Find(rt, y);
	Splay(x1, 0), Splay(x2, x1), Upd(rt);
	return x2;
}
void Del(int x) {
	if (!x) return ;
	b[sz --] = x, Del(lc), Del(rc);
}
int main()
{
	scanf ("%d%d", &n, &m);
	Rep(i, 1, N-1) b[i] = i; 
	Rep(i, 1, n) scanf ("%d", &a[i]);
	a[0] = a[n+1] = -inf;
	t[0].mx = -inf; 
	rt = Build(0, n+1);
	char str[15];
	Rep(i, 1, m) {
		scanf ("%s", str);
		int x, y, z, x2;
		if (str[0] == 'I') {
			scanf ("%d%d", &x, &n);
			Rep(j, 1, n) {
				scanf ("%d", &a[j]);
			}
			x = Get(x, x+1);
			Sc(x, Build(1, n), 0), Upd(x), Upd(rt);
		} else if (str[0] == 'D') {
			scanf ("%d%d", &x, &y);
			x = Get(x-1, x+y);
			Del(lc);
			t[x].ch[0] = 0, Upd(x), Upd(rt);
		} else if (str[0] == 'M' && str[2] == 'K') {
			scanf ("%d%d%d", &x, &y, &z);
			x = Get(x-1, x+y), Lc.lz = z, Upd(lc), Upd(x), Upd(rt);
		} else if (str[0] == 'R') {
			scanf ("%d%d", &x, &y);
			x = Get(x-1, x+y), Lc.rv ^= 1, Upd(lc), Upd(x), Upd(rt);
		} else if (str[0] == 'G') {
			scanf ("%d%d", &x, &y);
			x = Get(x-1, x+y);
			printf("%d\n", Lc.sum);
		} else {
			Upd(rt), printf ("%d\n", t[rt].mx);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值