POJ3580 SuperMemo

题意:维护一个长为n(n <= 100000)的序列,支持6种操作,区间加,区间反转,区间旋转,单点插入,单点删除,区间求最小值,操作个数m <= 100000.

分析:

裸的splay,不完全缩行后代码长度1913B,poj第一...

感谢zrt神犇对我的splay进行指导。

#include <cstdio>
#include <algorithm>
using namespace std;
#define l(x) t[x].s[0]
#define r(x) t[x].s[1]
#define f(x) t[x].p
#define ky l(r(rt))
#define lc(x) t[f(x)].s[1] == x
#define st(a,b,c) if(a) t[a].s[c] = b; if(b) f(b) = a;
const int N = 200010, inf = 0x3fffffff;
char op[10];
int n, q, tt, rt, x, y, z, a[N>>1];

struct nd {
	int s[2], v, sz, p, mi, fl, ad;
}t[N];
void pu(int x) {
	t[x].mi = min(t[x].v, min(t[l(x)].mi, t[r(x)].mi));
	t[x].sz = t[l(x)].sz + t[r(x)].sz + 1;
}
void pd(int x) {
	int d = t[x].ad;
	if(l(x)) t[l(x)].ad += d, t[l(x)].mi += d, t[l(x)].v += d;
	if(r(x)) t[r(x)].ad += d, t[r(x)].mi += d, t[r(x)].v += d;
	t[x].ad = 0;
	if(t[x].fl) t[l(x)].fl ^= 1, t[r(x)].fl ^= 1, swap(l(x), r(x)), t[x].fl = 0;
}
void bd(int l, int r, int p, int &x) {
	if(l > r) return;
	int m = (l + r) >> 1;
	t[x=++tt].p = p, t[x].v = a[m];
	bd(l, m-1, x, l(x)), bd(m+1, r, x, r(x));
	pu(x);
}
int rk(int k, int x) {
	pd(x);
	if(t[l(x)].sz + 1 == k) return x;
	if(t[l(x)].sz >= k) return rk(k, l(x));
	return rk(k-t[l(x)].sz-1, r(x));
}
void rot(int x) {
	int y = f(x), z = f(y), lx = lc(x), ly = lc(y);
	st(y, t[x].s[!lx], lx);
	st(z, x, ly);
	st(x, y, !lx);
	pu(y);
}
void sp(int x, int g = 0) {
	while(f(x) != g) rot(x);
	pu(x);
	if(!g) rt = x;
}

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	t[0].mi = t[0].v = inf;
	bd(0, n+1, 0, rt);
	scanf("%d", &q);
	while(q--) {
		scanf("%s", op);
		if(op[0] == 'A') {
			scanf("%d%d%d", &x, &y, &z);
			sp(rk(x, rt)), sp(rk(y+2, rt), rt);
			t[ky].v += z, t[ky].mi += z, t[ky].ad += z;
			pu(r(rt)), pu(rt);
		} else if(op[0] == 'M') {
			scanf("%d%d", &x, &y);
			sp(rk(x, rt)), sp(rk(y+2, rt), rt);
			printf("%d\n", t[ky].mi);
		} else if(op[0] == 'I') {
			scanf("%d%d", &x, &y);
			sp(rk(x+1, rt)), sp(rk(x+2, rt), rt);
			ky = ++tt;
			t[ky].p = r(rt), t[ky].v = t[ky].mi = y, t[ky].sz = 1;
			pu(r(rt)), pu(rt);
		} else if(op[0] == 'D') {
			scanf("%d", &x);
			sp(rk(x, rt)), sp(rk(x+2, rt), rt);
			t[ky].p = 0, ky = 0;
			pu(r(rt)), pu(rt);
		} else if(op[3] == 'E') {
			scanf("%d%d", &x, &y);
			sp(rk(x, rt)), sp(rk(y+2, rt), rt);
			t[ky].fl ^= 1;
		} else {
			scanf("%d%d%d", &x, &y, &z);
			z %= y-x+1;
			sp(rk(y-z+1, rt)), sp(rk(y+2, rt), rt);
			int tp = ky; ky = 0;
			pu(r(rt)), pu(rt);
			sp(rk(x, rt)), sp(rk(x+1, rt), rt);
			st(r(rt), tp, 0);
			pu(r(rt)), pu(rt);
		}
	}
	return 0;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值