发现单旋splay简单易懂,清晰明了,容易调试(?,貌似标记不弄错就不会出错),所以以后平衡树都写它算了。
贴代码,万一以后找不到了=。=!
没有什么好注释的。
1,需要注意的是这里splay(i,k)的含义是指通过splay操作时的i位置的左子树的节点为k;
2,一定要注意标记的下方和使用,以及0节点的情况。
3,一开始加了一个极左点和极后点,防止splay树为空,操作时需要注意;
4,树形态改变后及时updata,否则死都不知道死哪里了。
5,单旋splay可以适当随机提根。
noi2005 sequence :
# include <cstdlib>
# include <cmath>
# include <cstdio>
using namespace std;
const int oo = 107374189, maxn = 4000000+100;
int a[maxn], same[maxn],size[maxn], sum[maxn], maxl[maxn], maxr[maxn], maxs[maxn], link[maxn][2];
bool need[maxn], spin[maxn];
int m, n, root, pos, tot;
char c1, c2, c3;
inline void swap(int &x, int &y) {int tmp = x; x = y; y = tmp;};
inline int max(int x, int y) {return x > y? x: y;};
void updata(int i)
{
size[i]= size[link[i][0]] + size[link[i][1]] + 1;
sum[i] = sum[link[i][0]] + sum[link[i][1]] + a[i];
maxl[i] = max( maxl[link[i][0]], sum[link[i][0]] + maxl[link[i][1]] + a[i]);
maxr[i] = max( maxr[link[i][1]], sum[link[i][1]] + maxr[link[i][0]] + a[i]);
maxs[i] = max( max( maxs[link[i][0]], maxs[link[i][1]]), maxr[link[i][0]] + maxl[link[i][1]] + a[i]);
}
void release(int i)
{
if (i == 0) return;
a[i] = same[i], sum[i] = a[i]*size[i];
maxl[i] = maxr[i] = max(0, size[i]*a[i]);
maxs[i] = max(a[i], size[i]*a[i]);
need[i] = 1;
}
void handle(int i)
{
if (i == 0) return;
spin[i] ^= 1;
swap(maxl[i], maxr[i]);
}
void pushdown(int i)
{
if (need[i] != 0)
same[link[i][0]] = same[link[i][1]] = a[i] = same[i], same[i] = 0, need[i] = false,
spin[i] = 0, need[link[i][0]] = 1, need[link[i][1]] = 1, release(link[i][0]), release(link[i][1]), updata(i);
if (spin[i] != 0)
handle(link[i][0]), handle(link[i][1]), spin[i] = 0, swap(link[i][0], link[i][1]), updata(i);
}
void dfs(int i)
{
if (i == 0) return;
//if (need[i]) return;
int dl, dr, ds, dz;
dl=maxl[i];
dr=maxr[i];
ds=maxs[i], dz= size[i];
pushdown(i);
dfs(link[i][0]); dfs(link[i][1]);
updata(i);
i = i;
}
int build(int l, int r)
{
int mid = l+r>> 1;
if (l < mid) link[mid][0] = build(l, mid-1);
if (mid < r) link[mid][1] = build(mid+1, r);
updata(mid);
return mid;
}
void read()
{
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
int i;
scanf("%d%d", &n, &m); n+= 2; a[1] = -oo; a[n] = -oo; maxs[0] = -oo;
for (i = 1; i < n; i++) scanf("%d", &a[i+1]);
root = build(1, n);
}
void rotate(int &i, int p)
{
int j = link[i][p];
link[i][p] = link[j][!p];
link[j][!p] = i;
updata(i);updata(j);i = j;
}
void splay(int &i, int k)
{
pushdown(i);
int s = size[link[i][0]];
if (s < k) splay(link[i][1], k-s-1), rotate(i,1);
else if (s > k)splay(link[i][0], k), rotate(i,0);
}
inline void leave(int l, int r)
{
splay(root, r);
splay(link[root][0], l-2); updata(root);
}
void Insert()
{
int i;
for (i = 1; i <= 3; i++) scanf("%c", &c3);
scanf("%d%d", &pos, &tot); pos++;
for (i = 1; i <= tot; i++) scanf("%d", &a[n+i]); scanf("\n");
leave(pos+1, pos);
link[link[root][0]][1] = build(n+1, n+tot);
updata(link[root][0]); updata(root);
n+= tot;
}
void Delete()
{
int i;
for (i = 1; i <= 3; i++) scanf("%c", &c3);
scanf("%d%d\n", &pos, &tot);pos++;
leave(pos, pos+tot-1);
link[link[root][0]][1] = 0; updata(link[root][0]); updata(root);
// n -= tot;
}
void Makesame()
{
int i, c;
for (i = 1; i <= 6; i++) scanf("%c", &c3);
scanf("%d%d%d\n", &pos, &tot, &c); pos++;
leave(pos, pos+tot-1);
int d = link[link[root][0]][1]; need[d] = 1;
same[d] = c; release(d); updata(link[root][0]); updata(root);
}
void Reverse()
{
int i;
for (i = 1; i <= 4; i++) scanf("%c", &c3);
scanf("%d%d\n", &pos, &tot);pos++;
leave(pos, pos+tot-1);
int d = link[link[root][0]][1];
spin[d] ^= 1; swap(maxl[d], maxr[d]);
updata(link[root][0]); updata(root);
}
void Getsum()
{
int i; //dfs(root);
for (i = 1; i <= 4; i++) scanf("%c", &c3);
scanf("%d%d\n", &pos, &tot); pos++;
leave(pos, pos+tot-1);
printf("%d\n", sum[link[link[root][0]][1]]);
}
void Maxsum()
{
int i;
//dfs(root);
for (i = 1; i <= 4; i++) scanf("%c", &c3); scanf("\n");
printf("%d\n", maxs[root]);
}
int main()
{
read(); int i;
for (i = 1; i <= m; i++)
{
//dfs(root);
scanf("%c%c%c", &c1, &c2, &c3);
if (c1 == 'I') Insert();
else if (c1 == 'D') Delete();
else if (c1 == 'M' && c2 == 'A' && c3 == 'K') Makesame();
else if (c1 == 'R') Reverse();
else if (c1 == 'G') Getsum();
else if (c1 == 'M' && c2 == 'A' && c3 == 'X') Maxsum();
}
return 0;
}
hnoi2011 brackets:
# include <cstdlib>
# include <cstdio>
# include <cmath>
using namespace std;
const int maxn = 200000;
int sum[maxn], size[maxn], a[maxn], maxl[maxn], maxr[maxn], minl[maxn], minr[maxn], link[maxn][2], same[maxn];
bool spin[maxn], rev[maxn];
int i, n, m, root;
char tmp[10];
inline int max(int x, int y) {return x > y? x: y;};
inline int min(int x, int y) {return x < y? x: y;};
inline void swap(int &x, int &y) {int tmp = x; x = y; y = tmp;};
inline int abs(int x) {return x < 0? -x:x;};
void updata(int i)
{
size[i] = size[link[i][0]] + size[link[i][1]] + 1;
sum[i] = sum[link[i][0]] + a[i] + sum[link[i][1]];
maxl[i] = max(maxl[link[i][0]], sum[link[i][0]] + a[i] + maxl[link[i][1]]);
minl[i] = min(minl[link[i][0]], sum[link[i][0]] + a[i] + minl[link[i][1]]);
maxr[i] = max(maxr[link[i][1]], sum[link[i][1]] + a[i] + maxr[link[i][0]]);
minr[i] = min(minr[link[i][1]], sum[link[i][1]] + a[i] + minr[link[i][0]]);
}
int build(int l, int r)
{
int mid = l+r>>1;
if (l < mid) link[mid][0] = build(l, mid-1);
if (mid < r) link[mid][1] = build(mid+1, r);
updata(mid);
return mid;
}
void read()
{
freopen("brackets.in", "r", stdin);
freopen("brackets.out", "w", stdout);
scanf("%d%d\n", &n, &m); n+=2;
int i; char c;
for (i = 2; i < n; i++)
{
scanf("%c", &c);
a[i]= c== '(' ? 1:-1;
}
root = build(1,n);
scanf("\n");
}
void rotate(int &i, int p)
{
int j = link[i][p];
link[i][p] = link[j][!p];
link[j][!p] = i;
updata(i); updata(j); i = j;
}
void hsame(int i, int d)
{
if (!i) return;
same[i]=d; rev[i] = 0; spin[i] = 0;
sum[i] = size[i]*d; a[i]=d;
maxr[i]=maxl[i] = max(0, sum[i]);
minr[i]=minl[i] = min(0, sum[i]);
}
void hspin(int i)
{
if (!i) return;
spin[i]^= 1;
swap(link[i][0], link[i][1]);
swap(maxl[i], maxr[i]); swap(minl[i], minr[i]);
}
void hrev(int i)
{
if (!i) return;
rev[i]^= 1;
swap(maxl[i],minl[i]); swap(maxr[i],minr[i]);
maxl[i] = -maxl[i], maxr[i]= -maxr[i], minl[i] = -minl[i], minr[i] = -minr[i];
sum[i] = 0-sum[i]; a[i] = -a[i];
}
void pushdown(int i)
{
if (same[i] != 0)
hsame(link[i][0], same[i]), hsame(link[i][1], same[i]),
same[i] = 0;
if (rev[i] != 0)
hrev(link[i][0]), hrev(link[i][1]),
rev[i] = 0;
if (spin[i] != 0)
hspin(link[i][0]), hspin(link[i][1]),
spin[i] = 0;
}
void splay(int &i, int k)
{
pushdown(i);
int s = size[link[i][0]];
if (s > k) splay(link[i][0], k), rotate(i,0);
else if (s< k) splay(link[i][1], k-s-1), rotate(i,1);
updata(i);
}
void leave(int l, int r)
{
splay(root, r);
splay(link[root][0], l-2); updata(root);
}
void replace()
{
int l, r; char c;
scanf("%d%d ", &l, &r); scanf("%c\n", &c);
leave(++l, ++r);
hsame(link[link[root][0]][1], (c=='(')*2-1);
updata(link[root][0]); updata(root);
}
void swap()
{
int l, r;
scanf("%d%d\n", &l, &r);
leave(++l, ++r);
hspin(link[link[root][0]][1]);
updata(link[root][0]); updata(root);
}
void invert()
{
int l, r;
scanf("%d%d\n", &l, &r);
leave(++l, ++r);
hrev(link[link[root][0]][1]);
updata(link[root][0]); updata(root);
}
void dfs(int i)
{
if (!i) return;
pushdown(i);
dfs(link[i][0]); dfs(link[i][1]);
updata(i);
}
void query()
{
int l, r, u, v;
scanf("%d%d\n", &l, &r);
leave(++l, ++r);
//dfs(root);
int d= link[link[root][0]][1];
u = abs(minl[d]), v = abs(maxr[d]);
if (u & 1) printf("%d\n", u/2+v/2+2);
else printf("%d\n", (u+v)/2);
}
int main()
{
read();
for (i = 1; i <= m; i++)
{
scanf("%s", tmp);
if (tmp[0] == 'R') replace();
else if (tmp[0] == 'S') swap();
else if (tmp[0] == 'I') invert();
else query();
}
return 0;
}
poj 3580 supermemo:
# include <cstdlib>
# include <cstdio>
# include <cmath>
# include <ctime>
using namespace std;
const int oo = 1073741819, maxn = 300000+5;
int spin[maxn],a[maxn], link[maxn][2], sum[maxn], size[maxn], bj[maxn];
int n, m, root;
inline int min(int x, int y) {return x < y?x:y;}
inline void swap(int &x, int &y) {int tmp = x; x = y; y = tmp;}
inline void updata(int x)
{
sum[x] = min(a[x], min(sum[link[x][0]], sum[link[x][1]]));
size[x] = size[link[x][1]]+ 1 +size[link[x][0]];
}
int build(int l, int r)
{
int mid = l+r>>1;
if (l<mid) link[mid][0] = build(l, mid-1);
if (mid<r) link[mid][1] = build(mid+1, r);
updata(mid);
return mid;
}
void read()
{
freopen("3580.in", "r", stdin);
freopen("3580.out", "w", stdout);
scanf("%d", &n); n+= 2; a[0] = a[n] = sum[0] = sum[n] = oo;
for (int i = 2; i < n; i++) scanf("%d", &a[i]);
root = build(1, n);
}
void rotate(int &i, int p)
{
int j = link[i][p];
link[i][p] = link[j][!p];
link[j][!p] = i;
updata(i); updata(j); i=j;
}
inline void hbj(int i, int d)
{
if (!i) return;
bj[i] += d; sum[i]+= d; a[i] += d;
}
inline void hspin(int i)
{
if (!i) return;
spin[i]^=1; swap(link[i][0], link[i][1]);
}
inline void pushdown(int i)
{
if (!i) return;
if (spin[i])
hspin(link[i][0]), hspin(link[i][1]), spin[i] = 0;
if (bj[i] != 0)
hbj(link[i][0],bj[i]), hbj(link[i][1],bj[i]),bj[i]=0;
}
void splay(int &i, int k)
{
int s = size[link[i][0]];
pushdown(i);
if (s > k) splay(link[i][0], k), rotate(i, 0);
else if (s < k) splay(link[i][1], k-s-1), rotate(i, 1);
updata(i);
}
void leave(int l, int r)
{
splay(root, r);
splay(link[root][0], l-2);
updata(root);
}
void dfs(int i)
{
if (!i) return;
pushdown(i);
dfs(link[i][0]); dfs(link[i][1]);
updata(i);
}
int main()
{
srand(int(time (NULL)));
int have;
read(); int l,r,d,mid,x; char tmp[10]; have=n;
scanf("%d\n", &m);
for (int i = 1; i <= m; i++)
{
scanf("%s", tmp+1);
//dfs(root);
if (tmp[1]=='A')
{
scanf("%d%d%d\n", &l, &r, &d);
leave(++l, ++r); int c = link[link[root][0]][1];
hbj(c, d);updata(link[root][0]); updata(root);
}
else if (tmp[1]=='R'&&tmp[6]=='S')
{
scanf("%d%d\n", &l, &r);
leave(++l,++r); int c = link[link[root][0]][1];
hspin(c); updata(link[root][0]); updata(root);
}
else if (tmp[1]=='R'&&tmp[6]=='V')
{
scanf("%d%d%d\n", &l, &r, &d); ++l;++r;d %= r-l+1; mid=r-d;
if (!d) continue;
splay(root,mid-1), splay(link[root][0], l-2), splay(link[root][1], r-mid);
int u = link[root][0], v = link[root][1], tmp;
//tmp = link[v][0]; link[v][0] = link[u][1]; link[u][1] = 0;link[root][0] = tmp;
link[root][0] = link[u][1]; link[u][1] = link[v][0]; link[v][0] = 0;
updata(u); updata(v); updata(root);
splay(root,0); link[root][0] = u; updata(root);
}
else if (tmp[1]=='I')
{
scanf("%d%d\n", &x, &a[++n]);++x;
leave(x+1,x); int c = link[root][0];
link[c][1] = n; updata(n); updata(c); updata(root); ++have;
}
else if (tmp[1]=='D')
{
scanf("%d\n", &x);++x;
leave(x,x); int c = link[root][0];
link[c][1] = 0; updata(c); updata(root);--have;
}
else
{
scanf("%d%d\n", &l, &r);
leave(++l,++r); int c = link[link[root][0]][1];
//dfs(root);
printf("%d\n", sum[c]);
}
//splay(root, ((rand()<<15)+rand())%have);
//splay(root, ((rand()<<15)+rand())%have);
}
return 0;
}